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);
|
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||||
int (*removexattr) (struct dentry *, const char *);
|
int (*removexattr) (struct dentry *, const char *);
|
||||||
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
|
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
|
||||||
|
void (*update_time)(struct inode *, struct timespec *, int);
|
||||||
|
|
||||||
locking rules:
|
locking rules:
|
||||||
all may block
|
all may block
|
||||||
|
@ -87,6 +88,8 @@ getxattr: no
|
||||||
listxattr: no
|
listxattr: no
|
||||||
removexattr: yes
|
removexattr: yes
|
||||||
fiemap: no
|
fiemap: no
|
||||||
|
update_time: no
|
||||||
|
|
||||||
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
|
||||||
victim.
|
victim.
|
||||||
cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.
|
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 (*getxattr) (struct dentry *, const char *, void *, size_t);
|
||||||
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
ssize_t (*listxattr) (struct dentry *, char *, size_t);
|
||||||
int (*removexattr) (struct dentry *, const char *);
|
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
|
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
|
removexattr: called by the VFS to remove an extended attribute from
|
||||||
a file. This method is called by removexattr(2) system call.
|
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
|
The Address Space Object
|
||||||
========================
|
========================
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned int __kernel_ino_t;
|
typedef unsigned int __kernel_ino_t;
|
||||||
#define __kernel_ino_t __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 */
|
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
|
||||||
|
|
||||||
#include <asm-generic/posix_types.h>
|
#include <asm-generic/posix_types.h>
|
||||||
|
|
|
@ -22,9 +22,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned int __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
#ifndef _ASM_IA64_POSIX_TYPES_H
|
#ifndef _ASM_IA64_POSIX_TYPES_H
|
||||||
#define _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 */
|
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
|
||||||
|
|
||||||
#include <asm-generic/posix_types.h>
|
#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);
|
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 */
|
/* forward declaration */
|
||||||
static const struct dentry_operations pfmfs_dentry_operations;
|
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);
|
down_write(&task->mm->mmap_sem);
|
||||||
|
|
||||||
/* find some free area in address space, must have mmap sem held */
|
/* 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);
|
vma->vm_start = get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS);
|
||||||
if (vma->vm_start == 0UL) {
|
if (IS_ERR_VALUE(vma->vm_start)) {
|
||||||
DPRINT(("Cannot find unmapped area for size %ld\n", size));
|
DPRINT(("Cannot find unmapped area for size %ld\n", size));
|
||||||
up_write(&task->mm->mmap_sem);
|
up_write(&task->mm->mmap_sem);
|
||||||
goto error;
|
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,
|
ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags,
|
||||||
unsigned long new_addr)
|
unsigned long new_addr)
|
||||||
{
|
{
|
||||||
extern unsigned long do_mremap (unsigned long addr,
|
addr = sys_mremap(addr, old_len, new_len, flags, new_addr);
|
||||||
unsigned long old_len,
|
if (!IS_ERR((void *) addr))
|
||||||
unsigned long new_len,
|
force_successful_syscall_return();
|
||||||
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();
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,6 @@
|
||||||
* assume GCC is being used.
|
* 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;
|
typedef long __kernel_daddr_t;
|
||||||
#define __kernel_daddr_t __kernel_daddr_t
|
#define __kernel_daddr_t __kernel_daddr_t
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct stat {
|
||||||
long st_pad1[3]; /* Reserved for network id */
|
long st_pad1[3]; /* Reserved for network id */
|
||||||
ino_t st_ino;
|
ino_t st_ino;
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
nlink_t st_nlink;
|
__u32 st_nlink;
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
gid_t st_gid;
|
gid_t st_gid;
|
||||||
unsigned st_rdev;
|
unsigned st_rdev;
|
||||||
|
@ -55,7 +55,7 @@ struct stat64 {
|
||||||
unsigned long long st_ino;
|
unsigned long long st_ino;
|
||||||
|
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
nlink_t st_nlink;
|
__u32 st_nlink;
|
||||||
|
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
gid_t st_gid;
|
gid_t st_gid;
|
||||||
|
@ -96,7 +96,7 @@ struct stat {
|
||||||
unsigned long st_ino;
|
unsigned long st_ino;
|
||||||
|
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
nlink_t st_nlink;
|
__u32 st_nlink;
|
||||||
|
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
gid_t st_gid;
|
gid_t st_gid;
|
||||||
|
|
|
@ -20,9 +20,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __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 */
|
unsigned int st_dev; /* dev_t is 32 bits on parisc */
|
||||||
ino_t st_ino; /* 32 bits */
|
ino_t st_ino; /* 32 bits */
|
||||||
mode_t st_mode; /* 16 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_reserved1; /* old st_uid */
|
||||||
unsigned short st_reserved2; /* old st_gid */
|
unsigned short st_reserved2; /* old st_gid */
|
||||||
unsigned int st_rdev;
|
unsigned int st_rdev;
|
||||||
|
@ -42,7 +42,7 @@ struct hpux_stat64 {
|
||||||
unsigned int st_dev; /* dev_t is 32 bits on parisc */
|
unsigned int st_dev; /* dev_t is 32 bits on parisc */
|
||||||
ino_t st_ino; /* 32 bits */
|
ino_t st_ino; /* 32 bits */
|
||||||
mode_t st_mode; /* 16 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_reserved1; /* old st_uid */
|
||||||
unsigned short st_reserved2; /* old st_gid */
|
unsigned short st_reserved2; /* old st_gid */
|
||||||
unsigned int st_rdev;
|
unsigned int st_rdev;
|
||||||
|
|
|
@ -16,9 +16,6 @@ typedef int __kernel_ssize_t;
|
||||||
typedef long __kernel_ptrdiff_t;
|
typedef long __kernel_ptrdiff_t;
|
||||||
#define __kernel_size_t __kernel_size_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;
|
typedef short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -30,11 +30,11 @@ struct stat {
|
||||||
unsigned long st_dev;
|
unsigned long st_dev;
|
||||||
ino_t st_ino;
|
ino_t st_ino;
|
||||||
#ifdef __powerpc64__
|
#ifdef __powerpc64__
|
||||||
nlink_t st_nlink;
|
unsigned short st_nlink;
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
#else
|
#else
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
nlink_t st_nlink;
|
unsigned short st_nlink;
|
||||||
#endif
|
#endif
|
||||||
uid_t st_uid;
|
uid_t st_uid;
|
||||||
gid_t st_gid;
|
gid_t st_gid;
|
||||||
|
|
|
@ -24,7 +24,6 @@ typedef unsigned short __kernel_old_dev_t;
|
||||||
|
|
||||||
typedef unsigned long __kernel_ino_t;
|
typedef unsigned long __kernel_ino_t;
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
typedef unsigned short __kernel_nlink_t;
|
|
||||||
typedef unsigned short __kernel_ipc_pid_t;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
typedef unsigned short __kernel_uid_t;
|
typedef unsigned short __kernel_uid_t;
|
||||||
typedef unsigned short __kernel_gid_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_ino_t;
|
||||||
typedef unsigned int __kernel_mode_t;
|
typedef unsigned int __kernel_mode_t;
|
||||||
typedef unsigned int __kernel_nlink_t;
|
|
||||||
typedef int __kernel_ipc_pid_t;
|
typedef int __kernel_ipc_pid_t;
|
||||||
typedef unsigned int __kernel_uid_t;
|
typedef unsigned int __kernel_uid_t;
|
||||||
typedef unsigned int __kernel_gid_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_ino_t __kernel_ino_t
|
||||||
#define __kernel_mode_t __kernel_mode_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_ipc_pid_t __kernel_ipc_pid_t
|
||||||
#define __kernel_uid_t __kernel_uid_t
|
#define __kernel_uid_t __kernel_uid_t
|
||||||
#define __kernel_gid_t __kernel_gid_t
|
#define __kernel_gid_t __kernel_gid_t
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
typedef unsigned short __kernel_uid_t;
|
typedef unsigned short __kernel_uid_t;
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
|
||||||
typedef unsigned short __kernel_uid_t;
|
typedef unsigned short __kernel_uid_t;
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
#if defined(__sparc__) && defined(__arch64__)
|
#if defined(__sparc__) && defined(__arch64__)
|
||||||
/* sparc 64 bit */
|
/* 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_uid_t;
|
||||||
typedef unsigned short __kernel_old_gid_t;
|
typedef unsigned short __kernel_old_gid_t;
|
||||||
|
@ -38,9 +36,6 @@ typedef unsigned short __kernel_gid_t;
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef long __kernel_daddr_t;
|
||||||
#define __kernel_daddr_t __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_len, unsigned long, flags,
|
||||||
unsigned long, new_addr)
|
unsigned long, new_addr)
|
||||||
{
|
{
|
||||||
unsigned long ret = -EINVAL;
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_32BIT))
|
if (test_thread_flag(TIF_32BIT))
|
||||||
goto out;
|
return -EINVAL;
|
||||||
|
return sys_mremap(addr, old_len, new_len, flags, new_addr);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we come to here via sys_nis_syscall so it can setup the regs argument */
|
/* 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_mode_t compat_mode_t;
|
||||||
typedef __kernel_dev_t compat_dev_t;
|
typedef __kernel_dev_t compat_dev_t;
|
||||||
typedef __kernel_loff_t compat_loff_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_ipc_pid_t compat_ipc_pid_t;
|
||||||
typedef __kernel_daddr_t compat_daddr_t;
|
typedef __kernel_daddr_t compat_daddr_t;
|
||||||
typedef __kernel_fsid_t compat_fsid_t;
|
typedef __kernel_fsid_t compat_fsid_t;
|
||||||
|
|
|
@ -10,9 +10,6 @@
|
||||||
typedef unsigned short __kernel_mode_t;
|
typedef unsigned short __kernel_mode_t;
|
||||||
#define __kernel_mode_t __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;
|
typedef unsigned short __kernel_ipc_pid_t;
|
||||||
#define __kernel_ipc_pid_t __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;
|
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,
|
struct attribute *attr,
|
||||||
int index)
|
int index)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,11 +130,10 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* This is all entirely broken */
|
/* This is all entirely broken */
|
||||||
down_write(¤t->mm->mmap_sem);
|
|
||||||
old_fops = file_priv->filp->f_op;
|
old_fops = file_priv->filp->f_op;
|
||||||
file_priv->filp->f_op = &i810_buffer_fops;
|
file_priv->filp->f_op = &i810_buffer_fops;
|
||||||
dev_priv->mmap_buffer = buf;
|
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,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, buf->bus_address);
|
MAP_SHARED, buf->bus_address);
|
||||||
dev_priv->mmap_buffer = NULL;
|
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);
|
retcode = PTR_ERR(buf_priv->virtual);
|
||||||
buf_priv->virtual = NULL;
|
buf_priv->virtual = NULL;
|
||||||
}
|
}
|
||||||
up_write(¤t->mm->mmap_sem);
|
|
||||||
|
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,24 +68,6 @@ static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
|
||||||
return current_fsgid();
|
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)
|
static int v9fs_test_inode_dotl(struct inode *inode, void *data)
|
||||||
{
|
{
|
||||||
struct v9fs_inode *v9inode = V9FS_I(inode);
|
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)
|
if (dir->i_mode & S_ISGID)
|
||||||
omode |= S_ISGID;
|
omode |= S_ISGID;
|
||||||
|
|
||||||
dir_dentry = v9fs_dentry_from_dir_inode(dir);
|
dir_dentry = dentry->d_parent;
|
||||||
dfid = v9fs_fid_lookup(dir_dentry);
|
dfid = v9fs_fid_lookup(dir_dentry);
|
||||||
if (IS_ERR(dfid)) {
|
if (IS_ERR(dfid)) {
|
||||||
err = PTR_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);
|
dir->i_ino, old_dentry->d_name.name, dentry->d_name.name);
|
||||||
|
|
||||||
v9ses = v9fs_inode2v9ses(dir);
|
v9ses = v9fs_inode2v9ses(dir);
|
||||||
dir_dentry = v9fs_dentry_from_dir_inode(dir);
|
dir_dentry = dentry->d_parent;
|
||||||
dfid = v9fs_fid_lookup(dir_dentry);
|
dfid = v9fs_fid_lookup(dir_dentry);
|
||||||
if (IS_ERR(dfid))
|
if (IS_ERR(dfid))
|
||||||
return PTR_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;
|
return -EINVAL;
|
||||||
|
|
||||||
v9ses = v9fs_inode2v9ses(dir);
|
v9ses = v9fs_inode2v9ses(dir);
|
||||||
dir_dentry = v9fs_dentry_from_dir_inode(dir);
|
dir_dentry = dentry->d_parent;
|
||||||
dfid = v9fs_fid_lookup(dir_dentry);
|
dfid = v9fs_fid_lookup(dir_dentry);
|
||||||
if (IS_ERR(dfid)) {
|
if (IS_ERR(dfid)) {
|
||||||
err = PTR_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_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)])
|
#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_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_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)
|
#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;
|
info->mmap_size = nr_pages * PAGE_SIZE;
|
||||||
dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
|
dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
|
||||||
down_write(&ctx->mm->mmap_sem);
|
down_write(&ctx->mm->mmap_sem);
|
||||||
info->mmap_base = do_mmap(NULL, 0, info->mmap_size,
|
info->mmap_base = do_mmap_pgoff(NULL, 0, info->mmap_size,
|
||||||
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
|
PROT_READ|PROT_WRITE,
|
||||||
0);
|
MAP_ANONYMOUS|MAP_PRIVATE, 0);
|
||||||
if (IS_ERR((void *)info->mmap_base)) {
|
if (IS_ERR((void *)info->mmap_base)) {
|
||||||
up_write(&ctx->mm->mmap_sem);
|
up_write(&ctx->mm->mmap_sem);
|
||||||
info->mmap_size = 0;
|
info->mmap_size = 0;
|
||||||
|
|
|
@ -176,6 +176,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
|
||||||
return -EPERM;
|
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)) {
|
if ((ia_valid & ATTR_MODE)) {
|
||||||
umode_t amode = attr->ia_mode;
|
umode_t amode = attr->ia_mode;
|
||||||
/* Flag setting protected by i_mutex */
|
/* Flag setting protected by i_mutex */
|
||||||
|
|
|
@ -329,7 +329,6 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
|
||||||
if (!size)
|
if (!size)
|
||||||
return addr;
|
return addr;
|
||||||
|
|
||||||
down_write(¤t->mm->mmap_sem);
|
|
||||||
/*
|
/*
|
||||||
* total_size is the size of the ELF (interpreter) image.
|
* total_size is the size of the ELF (interpreter) image.
|
||||||
* The _first_ mmap needs to know the full size, otherwise
|
* 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) {
|
if (total_size) {
|
||||||
total_size = ELF_PAGEALIGN(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))
|
if (!BAD_ADDR(map_addr))
|
||||||
do_munmap(current->mm, map_addr+size, total_size-size);
|
vm_munmap(map_addr+size, total_size-size);
|
||||||
} else
|
} 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);
|
return(map_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -562,7 +562,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
realdatastart = (unsigned long) -ENOMEM;
|
realdatastart = (unsigned long) -ENOMEM;
|
||||||
printk("Unable to allocate RAM for process data, errno %d\n",
|
printk("Unable to allocate RAM for process data, errno %d\n",
|
||||||
(int)-realdatastart);
|
(int)-realdatastart);
|
||||||
do_munmap(current->mm, textpos, text_len);
|
vm_munmap(textpos, text_len);
|
||||||
ret = realdatastart;
|
ret = realdatastart;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -586,8 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
}
|
}
|
||||||
if (IS_ERR_VALUE(result)) {
|
if (IS_ERR_VALUE(result)) {
|
||||||
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
printk("Unable to read data+bss, errno %d\n", (int)-result);
|
||||||
do_munmap(current->mm, textpos, text_len);
|
vm_munmap(textpos, text_len);
|
||||||
do_munmap(current->mm, realdatastart, len);
|
vm_munmap(realdatastart, len);
|
||||||
ret = result;
|
ret = result;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -654,7 +654,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
}
|
}
|
||||||
if (IS_ERR_VALUE(result)) {
|
if (IS_ERR_VALUE(result)) {
|
||||||
printk("Unable to read code+data+bss, errno %d\n",(int)-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));
|
MAX_SHARED_LIBS * sizeof(unsigned long));
|
||||||
ret = result;
|
ret = result;
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -2974,7 +2974,6 @@ int btrfs_readpage(struct file *file, struct page *page);
|
||||||
void btrfs_evict_inode(struct inode *inode);
|
void btrfs_evict_inode(struct inode *inode);
|
||||||
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
|
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
|
||||||
int btrfs_dirty_inode(struct inode *inode);
|
int btrfs_dirty_inode(struct inode *inode);
|
||||||
int btrfs_update_time(struct file *file);
|
|
||||||
struct inode *btrfs_alloc_inode(struct super_block *sb);
|
struct inode *btrfs_alloc_inode(struct super_block *sb);
|
||||||
void btrfs_destroy_inode(struct inode *inode);
|
void btrfs_destroy_inode(struct inode *inode);
|
||||||
int btrfs_drop_inode(struct inode *inode);
|
int btrfs_drop_inode(struct inode *inode);
|
||||||
|
|
|
@ -13,15 +13,14 @@
|
||||||
parent_root_objectid) / 4)
|
parent_root_objectid) / 4)
|
||||||
#define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 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,
|
static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct btrfs_fid *fid = (struct btrfs_fid *)fh;
|
struct btrfs_fid *fid = (struct btrfs_fid *)fh;
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
int len = *max_len;
|
int len = *max_len;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
|
if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
|
||||||
*max_len = BTRFS_FID_SIZE_CONNECTABLE;
|
*max_len = BTRFS_FID_SIZE_CONNECTABLE;
|
||||||
return 255;
|
return 255;
|
||||||
} else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
|
} 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->root_objectid = BTRFS_I(inode)->root->objectid;
|
||||||
fid->gen = inode->i_generation;
|
fid->gen = inode->i_generation;
|
||||||
|
|
||||||
if (connectable && !S_ISDIR(inode->i_mode)) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
u64 parent_root_id;
|
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_objectid = BTRFS_I(parent)->location.objectid;
|
||||||
fid->parent_gen = parent->i_generation;
|
fid->parent_gen = parent->i_generation;
|
||||||
parent_root_id = BTRFS_I(parent)->root->objectid;
|
parent_root_id = BTRFS_I(parent)->root->objectid;
|
||||||
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
if (parent_root_id != fid->root_objectid) {
|
if (parent_root_id != fid->root_objectid) {
|
||||||
fid->parent_root_objectid = parent_root_id;
|
fid->parent_root_objectid = parent_root_id;
|
||||||
len = BTRFS_FID_SIZE_CONNECTABLE_ROOT;
|
len = BTRFS_FID_SIZE_CONNECTABLE_ROOT;
|
||||||
|
|
|
@ -1433,7 +1433,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = btrfs_update_time(file);
|
err = file_update_time(file);
|
||||||
if (err) {
|
if (err) {
|
||||||
mutex_unlock(&inode->i_mutex);
|
mutex_unlock(&inode->i_mutex);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -77,7 +77,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
|
||||||
return ERR_PTR(-ENOENT);
|
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;
|
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)
|
static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation)
|
||||||
{
|
{
|
||||||
u64 *val;
|
__le64 *val;
|
||||||
|
|
||||||
io_ctl_map_page(io_ctl, 1);
|
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)
|
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
|
* 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
|
* 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.
|
* 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;
|
if (flags & S_VERSION)
|
||||||
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)
|
|
||||||
inode_inc_iversion(inode);
|
inode_inc_iversion(inode);
|
||||||
if (sync_it & S_CTIME)
|
if (flags & S_CTIME)
|
||||||
inode->i_ctime = now;
|
inode->i_ctime = *now;
|
||||||
if (sync_it & S_MTIME)
|
if (flags & S_MTIME)
|
||||||
inode->i_mtime = now;
|
inode->i_mtime = *now;
|
||||||
ret = btrfs_dirty_inode(inode);
|
if (flags & S_ATIME)
|
||||||
if (!ret)
|
inode->i_atime = *now;
|
||||||
mark_inode_dirty_sync(inode);
|
return btrfs_dirty_inode(inode);
|
||||||
mnt_drop_write(file->f_path.mnt);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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);
|
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
ret = btrfs_update_time(vma->vm_file);
|
ret = file_update_time(vma->vm_file);
|
||||||
reserved = 1;
|
reserved = 1;
|
||||||
}
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -7635,6 +7607,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
|
||||||
.permission = btrfs_permission,
|
.permission = btrfs_permission,
|
||||||
.fiemap = btrfs_fiemap,
|
.fiemap = btrfs_fiemap,
|
||||||
.get_acl = btrfs_get_acl,
|
.get_acl = btrfs_get_acl,
|
||||||
|
.update_time = btrfs_update_time,
|
||||||
};
|
};
|
||||||
static const struct inode_operations btrfs_special_inode_operations = {
|
static const struct inode_operations btrfs_special_inode_operations = {
|
||||||
.getattr = btrfs_getattr,
|
.getattr = btrfs_getattr,
|
||||||
|
@ -7645,6 +7618,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.get_acl = btrfs_get_acl,
|
.get_acl = btrfs_get_acl,
|
||||||
|
.update_time = btrfs_update_time,
|
||||||
};
|
};
|
||||||
static const struct inode_operations btrfs_symlink_inode_operations = {
|
static const struct inode_operations btrfs_symlink_inode_operations = {
|
||||||
.readlink = generic_readlink,
|
.readlink = generic_readlink,
|
||||||
|
@ -7658,6 +7632,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
|
||||||
.listxattr = btrfs_listxattr,
|
.listxattr = btrfs_listxattr,
|
||||||
.removexattr = btrfs_removexattr,
|
.removexattr = btrfs_removexattr,
|
||||||
.get_acl = btrfs_get_acl,
|
.get_acl = btrfs_get_acl,
|
||||||
|
.update_time = btrfs_update_time,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct dentry_operations btrfs_dentry_operations = {
|
const struct dentry_operations btrfs_dentry_operations = {
|
||||||
|
|
|
@ -3152,7 +3152,7 @@ SYSCALL_DEFINE2(bdflush, int, func, long, data)
|
||||||
/*
|
/*
|
||||||
* Buffer-head allocation
|
* 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
|
* 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;
|
u32 parent_name_hash;
|
||||||
} __attribute__ ((packed));
|
} __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;
|
int type;
|
||||||
struct ceph_nfs_fh *fh = (void *)rawfh;
|
struct ceph_nfs_fh *fh = (void *)rawfh;
|
||||||
struct ceph_nfs_confh *cfh = (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 connected_handle_length = sizeof(*cfh)/4;
|
||||||
int handle_length = sizeof(*fh)/4;
|
int handle_length = sizeof(*fh)/4;
|
||||||
|
struct dentry *dentry = d_find_alias(inode);
|
||||||
|
struct dentry *parent;
|
||||||
|
|
||||||
/* don't re-export snaps */
|
/* don't re-export snaps */
|
||||||
if (ceph_snap(inode) != CEPH_NOSNAP)
|
if (ceph_snap(inode) != CEPH_NOSNAP)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
/* if we found an alias, generate a connectable fh */
|
||||||
parent = dentry->d_parent;
|
if (*max_len >= connected_handle_length && dentry) {
|
||||||
if (*max_len >= connected_handle_length) {
|
|
||||||
dout("encode_fh %p connectable\n", 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_ino = ceph_ino(parent->d_inode);
|
||||||
cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode,
|
cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode,
|
||||||
dentry);
|
dentry);
|
||||||
*max_len = connected_handle_length;
|
*max_len = connected_handle_length;
|
||||||
type = 2;
|
type = 2;
|
||||||
|
spin_unlock(&dentry->d_lock);
|
||||||
} else if (*max_len >= handle_length) {
|
} else if (*max_len >= handle_length) {
|
||||||
if (connectable) {
|
if (parent_inode) {
|
||||||
|
/* nfsd wants connectable */
|
||||||
*max_len = connected_handle_length;
|
*max_len = connected_handle_length;
|
||||||
type = 255;
|
type = 255;
|
||||||
} else {
|
} else {
|
||||||
dout("encode_fh %p\n", dentry);
|
dout("encode_fh %p\n", dentry);
|
||||||
fh->ino = ceph_ino(dentry->d_inode);
|
fh->ino = ceph_ino(inode);
|
||||||
*max_len = handle_length;
|
*max_len = handle_length;
|
||||||
type = 1;
|
type = 1;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +90,6 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
|
||||||
*max_len = handle_length;
|
*max_len = handle_length;
|
||||||
type = 255;
|
type = 255;
|
||||||
}
|
}
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
return type;
|
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;
|
int error;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
int fput_needed;
|
||||||
struct compat_readdir_callback buf;
|
struct compat_readdir_callback buf;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.result = 0;
|
buf.result = 0;
|
||||||
buf.dirent = dirent;
|
buf.dirent = dirent;
|
||||||
|
@ -885,8 +885,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
error = buf.result;
|
error = buf.result;
|
||||||
|
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,16 +952,15 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
|
||||||
struct file * file;
|
struct file * file;
|
||||||
struct compat_linux_dirent __user * lastdirent;
|
struct compat_linux_dirent __user * lastdirent;
|
||||||
struct compat_getdents_callback buf;
|
struct compat_getdents_callback buf;
|
||||||
|
int fput_needed;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EFAULT;
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.current_dir = dirent;
|
buf.current_dir = dirent;
|
||||||
buf.previous = NULL;
|
buf.previous = NULL;
|
||||||
|
@ -979,8 +977,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
|
||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,16 +1038,15 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
|
||||||
struct file * file;
|
struct file * file;
|
||||||
struct linux_dirent64 __user * lastdirent;
|
struct linux_dirent64 __user * lastdirent;
|
||||||
struct compat_getdents_callback64 buf;
|
struct compat_getdents_callback64 buf;
|
||||||
|
int fput_needed;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EFAULT;
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.current_dir = dirent;
|
buf.current_dir = dirent;
|
||||||
buf.previous = NULL;
|
buf.previous = NULL;
|
||||||
|
@ -1068,8 +1064,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
|
||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
|
#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
|
* d_find_alias - grab a hashed alias of inode
|
||||||
* @inode: inode in question
|
* @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,
|
* 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.
|
* acquire the reference to alias and return it. Otherwise return NULL.
|
||||||
|
@ -693,10 +691,9 @@ EXPORT_SYMBOL(dget_parent);
|
||||||
* of a filesystem.
|
* of a filesystem.
|
||||||
*
|
*
|
||||||
* If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
|
* If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
|
||||||
* any other hashed alias over that one unless @want_discon is set,
|
* any other hashed alias over that.
|
||||||
* in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias.
|
|
||||||
*/
|
*/
|
||||||
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;
|
struct dentry *alias, *discon_alias;
|
||||||
|
|
||||||
|
@ -708,7 +705,7 @@ again:
|
||||||
if (IS_ROOT(alias) &&
|
if (IS_ROOT(alias) &&
|
||||||
(alias->d_flags & DCACHE_DISCONNECTED)) {
|
(alias->d_flags & DCACHE_DISCONNECTED)) {
|
||||||
discon_alias = alias;
|
discon_alias = alias;
|
||||||
} else if (!want_discon) {
|
} else {
|
||||||
__dget_dlock(alias);
|
__dget_dlock(alias);
|
||||||
spin_unlock(&alias->d_lock);
|
spin_unlock(&alias->d_lock);
|
||||||
return alias;
|
return alias;
|
||||||
|
@ -739,7 +736,7 @@ struct dentry *d_find_alias(struct inode *inode)
|
||||||
|
|
||||||
if (!list_empty(&inode->i_dentry)) {
|
if (!list_empty(&inode->i_dentry)) {
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
de = __d_find_alias(inode, 0);
|
de = __d_find_alias(inode);
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
}
|
}
|
||||||
return de;
|
return de;
|
||||||
|
@ -1650,9 +1647,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
|
||||||
|
|
||||||
if (inode && S_ISDIR(inode->i_mode)) {
|
if (inode && S_ISDIR(inode->i_mode)) {
|
||||||
spin_lock(&inode->i_lock);
|
spin_lock(&inode->i_lock);
|
||||||
new = __d_find_alias(inode, 1);
|
new = __d_find_any_alias(inode);
|
||||||
if (new) {
|
if (new) {
|
||||||
BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
|
|
||||||
spin_unlock(&inode->i_lock);
|
spin_unlock(&inode->i_lock);
|
||||||
security_d_instantiate(new, inode);
|
security_d_instantiate(new, inode);
|
||||||
d_move(new, dentry);
|
d_move(new, dentry);
|
||||||
|
@ -2482,7 +2478,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
|
||||||
struct dentry *alias;
|
struct dentry *alias;
|
||||||
|
|
||||||
/* Does an aliased dentry already exist? */
|
/* Does an aliased dentry already exist? */
|
||||||
alias = __d_find_alias(inode, 0);
|
alias = __d_find_alias(inode);
|
||||||
if (alias) {
|
if (alias) {
|
||||||
actual = alias;
|
actual = alias;
|
||||||
write_seqlock(&rename_lock);
|
write_seqlock(&rename_lock);
|
||||||
|
@ -2575,7 +2571,7 @@ static int prepend_path(const struct path *path,
|
||||||
bool slash = false;
|
bool slash = false;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
while (dentry != root->dentry || vfsmnt != root->mnt) {
|
while (dentry != root->dentry || vfsmnt != root->mnt) {
|
||||||
struct dentry * parent;
|
struct dentry * parent;
|
||||||
|
|
||||||
|
@ -2606,7 +2602,7 @@ static int prepend_path(const struct path *path,
|
||||||
error = prepend(buffer, buflen, "/", 1);
|
error = prepend(buffer, buflen, "/", 1);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
global_root:
|
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);
|
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
|
||||||
char *lower_buf;
|
char *lower_buf;
|
||||||
size_t lower_bufsiz = PATH_MAX;
|
|
||||||
mm_segment_t old_fs;
|
mm_segment_t old_fs;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
|
lower_buf = kmalloc(PATH_MAX, GFP_KERNEL);
|
||||||
if (!lower_buf) {
|
if (!lower_buf) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -673,58 +672,29 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
|
||||||
set_fs(get_ds());
|
set_fs(get_ds());
|
||||||
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
|
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
|
||||||
(char __user *)lower_buf,
|
(char __user *)lower_buf,
|
||||||
lower_bufsiz);
|
PATH_MAX);
|
||||||
set_fs(old_fs);
|
set_fs(old_fs);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto out;
|
goto out;
|
||||||
lower_bufsiz = rc;
|
|
||||||
rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
|
rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
|
||||||
lower_buf, lower_bufsiz);
|
lower_buf, rc);
|
||||||
out:
|
out:
|
||||||
kfree(lower_buf);
|
kfree(lower_buf);
|
||||||
return rc;
|
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)
|
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
char *buf;
|
char *buf;
|
||||||
int len = PAGE_SIZE, rc;
|
size_t len = PATH_MAX;
|
||||||
mm_segment_t old_fs;
|
int rc;
|
||||||
|
|
||||||
/* Released in ecryptfs_put_link(); only release here on error */
|
rc = ecryptfs_readlink_lower(dentry, &buf, &len);
|
||||||
buf = kmalloc(len, GFP_KERNEL);
|
if (rc)
|
||||||
if (!buf) {
|
|
||||||
buf = ERR_PTR(-ENOMEM);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
fsstack_copy_attr_atime(dentry->d_inode,
|
||||||
old_fs = get_fs();
|
ecryptfs_dentry_to_lower(dentry)->d_inode);
|
||||||
set_fs(get_ds());
|
buf[len] = '\0';
|
||||||
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';
|
|
||||||
out:
|
out:
|
||||||
nd_set_link(nd, buf);
|
nd_set_link(nd, buf);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1153,7 +1123,7 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct inode_operations ecryptfs_symlink_iops = {
|
const struct inode_operations ecryptfs_symlink_iops = {
|
||||||
.readlink = ecryptfs_readlink,
|
.readlink = generic_readlink,
|
||||||
.follow_link = ecryptfs_follow_link,
|
.follow_link = ecryptfs_follow_link,
|
||||||
.put_link = ecryptfs_put_link,
|
.put_link = ecryptfs_put_link,
|
||||||
.permission = ecryptfs_permission,
|
.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);
|
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||||
INIT_LIST_HEAD(&vma->anon_vma_chain);
|
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);
|
err = insert_vm_struct(mm, vma);
|
||||||
if (err)
|
if (err)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
@ -304,24 +304,23 @@ out:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* export_encode_fh - default export_operations->encode_fh function
|
* 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
|
* @fh: where to store the file handle fragment
|
||||||
* @max_len: maximum length to store there
|
* @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
|
* This default encode_fh function assumes that the 32 inode number
|
||||||
* is suitable for locating an inode, and that the generation 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
|
* 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.
|
* filehandle fragment where export_decode_fh expects to find them.
|
||||||
*/
|
*/
|
||||||
static int export_encode_fh(struct dentry *dentry, struct fid *fid,
|
static int export_encode_fh(struct inode *inode, struct fid *fid,
|
||||||
int *max_len, int connectable)
|
int *max_len, struct inode *parent)
|
||||||
{
|
{
|
||||||
struct inode * inode = dentry->d_inode;
|
|
||||||
int len = *max_len;
|
int len = *max_len;
|
||||||
int type = FILEID_INO32_GEN;
|
int type = FILEID_INO32_GEN;
|
||||||
|
|
||||||
if (connectable && (len < 4)) {
|
if (parent && (len < 4)) {
|
||||||
*max_len = 4;
|
*max_len = 4;
|
||||||
return 255;
|
return 255;
|
||||||
} else if (len < 2) {
|
} else if (len < 2) {
|
||||||
|
@ -332,14 +331,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
|
||||||
len = 2;
|
len = 2;
|
||||||
fid->i32.ino = inode->i_ino;
|
fid->i32.ino = inode->i_ino;
|
||||||
fid->i32.gen = inode->i_generation;
|
fid->i32.gen = inode->i_generation;
|
||||||
if (connectable && !S_ISDIR(inode->i_mode)) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
parent = dentry->d_parent->d_inode;
|
|
||||||
fid->i32.parent_ino = parent->i_ino;
|
fid->i32.parent_ino = parent->i_ino;
|
||||||
fid->i32.parent_gen = parent->i_generation;
|
fid->i32.parent_gen = parent->i_generation;
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
len = 4;
|
len = 4;
|
||||||
type = FILEID_INO32_GEN_PARENT;
|
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;
|
const struct export_operations *nop = dentry->d_sb->s_export_op;
|
||||||
int error;
|
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)
|
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
|
else
|
||||||
error = export_encode_fh(dentry, fid, max_len, connectable);
|
error = export_encode_fh(inode, fid, max_len, parent);
|
||||||
|
dput(p);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -735,10 +735,9 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
int len = *lenp;
|
||||||
struct inode *inode = de->d_inode;
|
|
||||||
u32 ipos_h, ipos_m, ipos_l;
|
u32 ipos_h, ipos_m, ipos_l;
|
||||||
|
|
||||||
if (len < 5) {
|
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[1] = inode->i_generation;
|
||||||
fh[2] = ipos_h;
|
fh[2] = ipos_h;
|
||||||
fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
|
fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
|
||||||
spin_lock(&de->d_lock);
|
fh[4] = ipos_l;
|
||||||
fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
|
if (parent)
|
||||||
spin_unlock(&de->d_lock);
|
fh[4] |= MSDOS_I(parent)->i_logstart;
|
||||||
return 3;
|
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)
|
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
|
||||||
{
|
{
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
|
int fput_needed;
|
||||||
long err = -EBADF;
|
long err = -EBADF;
|
||||||
|
|
||||||
filp = fget_raw(fd);
|
filp = fget_raw_light(fd, &fput_needed);
|
||||||
if (!filp)
|
if (!filp)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (unlikely(filp->f_mode & FMODE_PATH)) {
|
if (unlikely(filp->f_mode & FMODE_PATH)) {
|
||||||
if (!check_fcntl_cmd(cmd)) {
|
if (!check_fcntl_cmd(cmd))
|
||||||
fput(filp);
|
goto out1;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_file_fcntl(filp, cmd, arg);
|
err = security_file_fcntl(filp, cmd, arg);
|
||||||
if (err) {
|
if (!err)
|
||||||
fput(filp);
|
err = do_fcntl(fd, cmd, arg, filp);
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = do_fcntl(fd, cmd, arg, filp);
|
out1:
|
||||||
|
fput_light(filp, fput_needed);
|
||||||
fput(filp);
|
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -473,26 +469,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
|
||||||
unsigned long, arg)
|
unsigned long, arg)
|
||||||
{
|
{
|
||||||
struct file * filp;
|
struct file * filp;
|
||||||
long err;
|
long err = -EBADF;
|
||||||
|
int fput_needed;
|
||||||
|
|
||||||
err = -EBADF;
|
filp = fget_raw_light(fd, &fput_needed);
|
||||||
filp = fget_raw(fd);
|
|
||||||
if (!filp)
|
if (!filp)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (unlikely(filp->f_mode & FMODE_PATH)) {
|
if (unlikely(filp->f_mode & FMODE_PATH)) {
|
||||||
if (!check_fcntl_cmd(cmd)) {
|
if (!check_fcntl_cmd(cmd))
|
||||||
fput(filp);
|
goto out1;
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = security_file_fcntl(filp, cmd, arg);
|
err = security_file_fcntl(filp, cmd, arg);
|
||||||
if (err) {
|
if (err)
|
||||||
fput(filp);
|
goto out1;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
err = -EBADF;
|
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETLK64:
|
case F_GETLK64:
|
||||||
|
@ -507,7 +498,8 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
|
||||||
err = do_fcntl(fd, cmd, arg, filp);
|
err = do_fcntl(fd, cmd, arg, filp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fput(filp);
|
out1:
|
||||||
|
fput_light(filp, fput_needed);
|
||||||
out:
|
out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ struct files_stat_struct files_stat = {
|
||||||
.max_files = NR_FILE
|
.max_files = NR_FILE
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_LGLOCK(files_lglock);
|
|
||||||
DEFINE_LGLOCK(files_lglock);
|
DEFINE_LGLOCK(files_lglock);
|
||||||
|
|
||||||
/* SLAB cache for file structures */
|
/* 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)
|
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);
|
__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)
|
void file_sb_list_del(struct file *file)
|
||||||
{
|
{
|
||||||
if (!list_empty(&file->f_u.fu_list)) {
|
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);
|
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;
|
struct file *f;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
lg_global_lock(files_lglock);
|
lg_global_lock(&files_lglock);
|
||||||
do_file_list_for_each_entry(sb, f) {
|
do_file_list_for_each_entry(sb, f) {
|
||||||
struct vfsmount *mnt;
|
struct vfsmount *mnt;
|
||||||
if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
|
if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
|
||||||
|
@ -502,12 +501,12 @@ retry:
|
||||||
file_release_write(f);
|
file_release_write(f);
|
||||||
mnt = mntget(f->f_path.mnt);
|
mnt = mntget(f->f_path.mnt);
|
||||||
/* This can sleep, so we can't hold the spinlock. */
|
/* This can sleep, so we can't hold the spinlock. */
|
||||||
lg_global_unlock(files_lglock);
|
lg_global_unlock(&files_lglock);
|
||||||
mnt_drop_write(mnt);
|
mnt_drop_write(mnt);
|
||||||
mntput(mnt);
|
mntput(mnt);
|
||||||
goto retry;
|
goto retry;
|
||||||
} while_file_list_for_each_entry;
|
} while_file_list_for_each_entry;
|
||||||
lg_global_unlock(files_lglock);
|
lg_global_unlock(&files_lglock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init files_init(unsigned long mempages)
|
void __init files_init(unsigned long mempages)
|
||||||
|
@ -525,6 +524,6 @@ void __init files_init(unsigned long mempages)
|
||||||
n = (mempages * (PAGE_SIZE / 1024)) / 10;
|
n = (mempages * (PAGE_SIZE / 1024)) / 10;
|
||||||
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
|
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
|
||||||
files_defer_init();
|
files_defer_init();
|
||||||
lg_lock_init(files_lglock);
|
lg_lock_init(&files_lglock, "files_lglock");
|
||||||
percpu_counter_init(&nr_files, 0);
|
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)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
file_update_time(file);
|
err = file_update_time(file);
|
||||||
|
if (err)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (file->f_flags & O_DIRECT) {
|
if (file->f_flags & O_DIRECT) {
|
||||||
written = generic_file_direct_write(iocb, iov, &nr_segs,
|
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);
|
return ERR_PTR(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
|
static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
int len = parent ? 6 : 3;
|
||||||
bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
|
|
||||||
int len = encode_parent ? 6 : 3;
|
|
||||||
u64 nodeid;
|
u64 nodeid;
|
||||||
u32 generation;
|
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[1] = (u32)(nodeid & 0xffffffff);
|
||||||
fh[2] = generation;
|
fh[2] = generation;
|
||||||
|
|
||||||
if (encode_parent) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
parent = dentry->d_parent->d_inode;
|
|
||||||
nodeid = get_fuse_inode(parent)->nodeid;
|
nodeid = get_fuse_inode(parent)->nodeid;
|
||||||
generation = parent->i_generation;
|
generation = parent->i_generation;
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
fh[3] = (u32)(nodeid >> 32);
|
fh[3] = (u32)(nodeid >> 32);
|
||||||
fh[4] = (u32)(nodeid & 0xffffffff);
|
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;
|
*max_len = len;
|
||||||
return encode_parent ? 0x82 : 0x81;
|
return parent ? 0x82 : 0x81;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
|
static struct dentry *fuse_fh_to_dentry(struct super_block *sb,
|
||||||
|
|
|
@ -28,15 +28,14 @@
|
||||||
#define GFS2_LARGE_FH_SIZE 8
|
#define GFS2_LARGE_FH_SIZE 8
|
||||||
#define GFS2_OLD_FH_SIZE 10
|
#define GFS2_OLD_FH_SIZE 10
|
||||||
|
|
||||||
static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
|
static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
__be32 *fh = (__force __be32 *)p;
|
__be32 *fh = (__force __be32 *)p;
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
struct super_block *sb = inode->i_sb;
|
struct super_block *sb = inode->i_sb;
|
||||||
struct gfs2_inode *ip = GFS2_I(inode);
|
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;
|
*len = GFS2_LARGE_FH_SIZE;
|
||||||
return 255;
|
return 255;
|
||||||
} else if (*len < GFS2_SMALL_FH_SIZE) {
|
} 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);
|
fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
|
||||||
*len = GFS2_SMALL_FH_SIZE;
|
*len = GFS2_SMALL_FH_SIZE;
|
||||||
|
|
||||||
if (!connectable || inode == sb->s_root->d_inode)
|
if (!parent || inode == sb->s_root->d_inode)
|
||||||
return *len;
|
return *len;
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
ip = GFS2_I(parent);
|
||||||
inode = dentry->d_parent->d_inode;
|
|
||||||
ip = GFS2_I(inode);
|
|
||||||
igrab(inode);
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
|
fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
|
||||||
fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
|
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);
|
fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
|
||||||
*len = GFS2_LARGE_FH_SIZE;
|
*len = GFS2_LARGE_FH_SIZE;
|
||||||
|
|
||||||
iput(inode);
|
|
||||||
|
|
||||||
return *len;
|
return *len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
|
static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
|
||||||
{
|
{
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
u32 *bmp;
|
__le32 *bmp;
|
||||||
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail;
|
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);
|
hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec);
|
||||||
goto fail1;
|
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)
|
static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigned forward)
|
||||||
{
|
{
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
unsigned *bmp;
|
__le32 *bmp;
|
||||||
unsigned bs = near & ~0x3fff;
|
unsigned bs = near & ~0x3fff;
|
||||||
unsigned nr = (near & 0x3fff) & ~(n - 1);
|
unsigned nr = (near & 0x3fff) & ~(n - 1);
|
||||||
/*unsigned mnr;*/
|
/*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)
|
int hpfs_alloc_if_possible(struct super_block *s, secno sec)
|
||||||
{
|
{
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
u32 *bmp;
|
__le32 *bmp;
|
||||||
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end;
|
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end;
|
||||||
if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) {
|
if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) {
|
||||||
bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(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)
|
void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
|
||||||
{
|
{
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
u32 *bmp;
|
__le32 *bmp;
|
||||||
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
struct hpfs_sb_info *sbi = hpfs_sb(s);
|
||||||
/*printk("2 - ");*/
|
/*printk("2 - ");*/
|
||||||
if (!n) return;
|
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 n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14;
|
||||||
int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;
|
int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;
|
||||||
int i, j;
|
int i, j;
|
||||||
u32 *bmp;
|
__le32 *bmp;
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
||||||
for (j = 0; j < 512; j++) {
|
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);
|
hpfs_free_sectors(s, dno, 4);
|
||||||
} else {
|
} else {
|
||||||
struct quad_buffer_head qbh;
|
struct quad_buffer_head qbh;
|
||||||
u32 *bmp;
|
__le32 *bmp;
|
||||||
unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4;
|
unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4;
|
||||||
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
|
||||||
int c1, c2 = 0;
|
int c1, c2 = 0;
|
||||||
go_down:
|
go_down:
|
||||||
if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
|
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++)
|
for (i = 0; i < btree->n_used_nodes; i++)
|
||||||
if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
|
if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
|
||||||
a = le32_to_cpu(btree->u.internal[i].down);
|
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);
|
brelse(bh);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (btree->internal) {
|
if (bp_internal(btree)) {
|
||||||
a = le32_to_cpu(btree->u.internal[n].down);
|
a = le32_to_cpu(btree->u.internal[n].down);
|
||||||
btree->u.internal[n].file_secno = cpu_to_le32(-1);
|
btree->u.internal[n].file_secno = cpu_to_le32(-1);
|
||||||
mark_buffer_dirty(bh);
|
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) {
|
if (a == node && fnod) {
|
||||||
anode->up = cpu_to_le32(node);
|
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.n_used_nodes = btree->n_used_nodes;
|
||||||
anode->btree.first_free = btree->first_free;
|
anode->btree.first_free = btree->first_free;
|
||||||
anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
|
anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
|
||||||
memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
|
memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
|
||||||
btree->internal = 1;
|
btree->flags |= BP_internal;
|
||||||
btree->n_free_nodes = 11;
|
btree->n_free_nodes = 11;
|
||||||
btree->n_used_nodes = 1;
|
btree->n_used_nodes = 1;
|
||||||
btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree);
|
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);
|
hpfs_free_sectors(s, ra, 1);
|
||||||
if ((anode = hpfs_map_anode(s, na, &bh))) {
|
if ((anode = hpfs_map_anode(s, na, &bh))) {
|
||||||
anode->up = cpu_to_le32(up);
|
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);
|
mark_buffer_dirty(bh);
|
||||||
brelse(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))) {
|
if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {
|
||||||
anode = new_anode;
|
anode = new_anode;
|
||||||
/*anode->up = cpu_to_le32(up != -1 ? up : ra);*/
|
/*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_used_nodes = 1;
|
||||||
anode->btree.n_free_nodes = 59;
|
anode->btree.n_free_nodes = 59;
|
||||||
anode->btree.first_free = cpu_to_le16(16);
|
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))) {
|
if ((anode = hpfs_map_anode(s, na, &bh))) {
|
||||||
anode->up = cpu_to_le32(node);
|
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);
|
mark_buffer_dirty(bh);
|
||||||
brelse(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);
|
ranode->up = cpu_to_le32(node);
|
||||||
memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
|
memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
|
||||||
if (fnod) ranode->btree.fnode_parent = 1;
|
if (fnod)
|
||||||
ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
|
ranode->btree.flags |= BP_fnode_parent;
|
||||||
if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
|
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;
|
struct anode *unode;
|
||||||
if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
|
if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
|
||||||
unode->up = cpu_to_le32(ra);
|
unode->up = cpu_to_le32(ra);
|
||||||
unode->btree.fnode_parent = 0;
|
unode->btree.flags &= ~BP_fnode_parent;
|
||||||
mark_buffer_dirty(bh1);
|
mark_buffer_dirty(bh1);
|
||||||
brelse(bh1);
|
brelse(bh1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btree->internal = 1;
|
btree->flags |= BP_internal;
|
||||||
btree->n_free_nodes = fnod ? 10 : 58;
|
btree->n_free_nodes = fnod ? 10 : 58;
|
||||||
btree->n_used_nodes = 2;
|
btree->n_used_nodes = 2;
|
||||||
btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree);
|
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;
|
int d1, d2;
|
||||||
go_down:
|
go_down:
|
||||||
d2 = 0;
|
d2 = 0;
|
||||||
while (btree1->internal) {
|
while (bp_internal(btree1)) {
|
||||||
ano = le32_to_cpu(btree1->u.internal[pos].down);
|
ano = le32_to_cpu(btree1->u.internal[pos].down);
|
||||||
if (level) brelse(bh);
|
if (level) brelse(bh);
|
||||||
if (hpfs_sb(s)->sb_chk)
|
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_free_nodes = 8;
|
||||||
btree->n_used_nodes = 0;
|
btree->n_used_nodes = 0;
|
||||||
btree->first_free = cpu_to_le16(8);
|
btree->first_free = cpu_to_le16(8);
|
||||||
btree->internal = 0;
|
btree->flags &= ~BP_internal;
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
} else hpfs_free_sectors(s, f, 1);
|
} else hpfs_free_sectors(s, f, 1);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (btree->internal) {
|
while (bp_internal(btree)) {
|
||||||
nodes = btree->n_used_nodes + btree->n_free_nodes;
|
nodes = btree->n_used_nodes + btree->n_free_nodes;
|
||||||
for (i = 0; i < btree->n_used_nodes; i++)
|
for (i = 0; i < btree->n_used_nodes; i++)
|
||||||
if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
|
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;
|
||||||
struct extended_attribute *ea_end;
|
struct extended_attribute *ea_end;
|
||||||
if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return;
|
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));
|
else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno));
|
||||||
ea_end = fnode_end_ea(fnode);
|
ea_end = fnode_end_ea(fnode);
|
||||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||||
if (ea->indirect)
|
if (ea_indirect(ea))
|
||||||
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));
|
||||||
hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l));
|
hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l));
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
hpfs_free_sectors(s, fno, 1);
|
hpfs_free_sectors(s, fno, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
|
||||||
ret = -EIOERROR;
|
ret = -EIOERROR;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!fno->dirflag) {
|
if (!fnode_is_dir(fno)) {
|
||||||
e = 1;
|
e = 1;
|
||||||
hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
|
hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
|
||||||
(unsigned long)inode->i_ino);
|
(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->length = cpu_to_le16(36);
|
||||||
de->down = 1;
|
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);
|
memmove((char *)de + d_size, de, (char *)de_end - (char *)de);
|
||||||
memset(de, 0, d_size);
|
memset(de, 0, d_size);
|
||||||
if (down_ptr) {
|
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->down = 1;
|
||||||
}
|
}
|
||||||
de->length = cpu_to_le16(d_size);
|
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;
|
del->down = 0;
|
||||||
d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
|
d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
|
||||||
} else if (down)
|
} 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;
|
} else goto endm;
|
||||||
if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) {
|
if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) {
|
||||||
printk("HPFS: out of memory for dtree balancing\n");
|
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;
|
de_prev->down = 1;
|
||||||
dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
|
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_mark_4buffers_dirty(&qbh);
|
||||||
hpfs_brelse4(&qbh);
|
hpfs_brelse4(&qbh);
|
||||||
for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);
|
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);
|
kfree(name2);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!upf->dirflag) {
|
if (!fnode_is_dir(upf)) {
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));
|
hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));
|
||||||
kfree(name2);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
|
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
|
||||||
if (ea->indirect) {
|
if (ea_indirect(ea)) {
|
||||||
if (ea_valuelen(ea) != 8) {
|
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);
|
ano ? "anode" : "sectors", a, pos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
|
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
|
||||||
return;
|
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;
|
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);
|
struct extended_attribute *ea_end = fnode_end_ea(fnode);
|
||||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect)
|
if (ea_indirect(ea))
|
||||||
goto indirect;
|
goto indirect;
|
||||||
if (ea_valuelen(ea) >= size)
|
if (ea_valuelen(ea) >= size)
|
||||||
return -EINVAL;
|
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);
|
a = le32_to_cpu(fnode->ea_secno);
|
||||||
len = le32_to_cpu(fnode->ea_size_l);
|
len = le32_to_cpu(fnode->ea_size_l);
|
||||||
ano = fnode->ea_anode;
|
ano = fnode_in_anode(fnode);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
ea = (struct extended_attribute *)ex;
|
ea = (struct extended_attribute *)ex;
|
||||||
|
@ -101,10 +101,10 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) 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;
|
return -EIO;
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect)
|
if (ea_indirect(ea))
|
||||||
goto indirect;
|
goto indirect;
|
||||||
if (ea_valuelen(ea) >= size)
|
if (ea_valuelen(ea) >= size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -119,7 +119,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
|
||||||
indirect:
|
indirect:
|
||||||
if (ea_len(ea) >= size)
|
if (ea_len(ea) >= size)
|
||||||
return -EINVAL;
|
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;
|
return -EIO;
|
||||||
buf[ea_len(ea)] = 0;
|
buf[ea_len(ea)] = 0;
|
||||||
return 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);
|
struct extended_attribute *ea_end = fnode_end_ea(fnode);
|
||||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect)
|
if (ea_indirect(ea))
|
||||||
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(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))) {
|
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
|
||||||
printk("HPFS: out of memory for EA\n");
|
printk("HPFS: out of memory for EA\n");
|
||||||
return NULL;
|
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);
|
a = le32_to_cpu(fnode->ea_secno);
|
||||||
len = le32_to_cpu(fnode->ea_size_l);
|
len = le32_to_cpu(fnode->ea_size_l);
|
||||||
ano = fnode->ea_anode;
|
ano = fnode_in_anode(fnode);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
char ex[4 + 255 + 1 + 8];
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) 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;
|
return NULL;
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect)
|
if (ea_indirect(ea))
|
||||||
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(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))) {
|
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
|
||||||
printk("HPFS: out of memory for EA\n");
|
printk("HPFS: out of memory for EA\n");
|
||||||
return NULL;
|
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);
|
struct extended_attribute *ea_end = fnode_end_ea(fnode);
|
||||||
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect) {
|
if (ea_indirect(ea)) {
|
||||||
if (ea_len(ea) == size)
|
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) {
|
} else if (ea_valuelen(ea) == size) {
|
||||||
memcpy(ea_data(ea), data, 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);
|
a = le32_to_cpu(fnode->ea_secno);
|
||||||
len = le32_to_cpu(fnode->ea_size_l);
|
len = le32_to_cpu(fnode->ea_size_l);
|
||||||
ano = fnode->ea_anode;
|
ano = fnode_in_anode(fnode);
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (pos < len) {
|
while (pos < len) {
|
||||||
char ex[4 + 255 + 1 + 8];
|
char ex[4 + 255 + 1 + 8];
|
||||||
|
@ -220,12 +220,12 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) 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;
|
return;
|
||||||
if (!strcmp(ea->name, key)) {
|
if (!strcmp(ea->name, key)) {
|
||||||
if (ea->indirect) {
|
if (ea_indirect(ea)) {
|
||||||
if (ea_len(ea) == size)
|
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 {
|
else {
|
||||||
if (ea_valuelen(ea) == size)
|
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) {
|
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",
|
hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
|
||||||
(unsigned long)inode->i_ino,
|
(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;
|
return;
|
||||||
}
|
}
|
||||||
if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
|
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_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
|
||||||
fnode->ea_size_s = cpu_to_le16(0);
|
fnode->ea_size_s = cpu_to_le16(0);
|
||||||
fnode->ea_secno = cpu_to_le32(n);
|
fnode->ea_secno = cpu_to_le32(n);
|
||||||
fnode->ea_anode = cpu_to_le32(0);
|
fnode->flags &= ~FNODE_anode;
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
brelse(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);
|
secno q = hpfs_alloc_sector(s, fno, 1, 0);
|
||||||
if (!q) goto bail;
|
if (!q) goto bail;
|
||||||
fnode->ea_secno = cpu_to_le32(q);
|
fnode->ea_secno = cpu_to_le32(q);
|
||||||
fnode->ea_anode = 0;
|
fnode->flags &= ~FNODE_anode;
|
||||||
len++;
|
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)) {
|
if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
|
||||||
len++;
|
len++;
|
||||||
} else {
|
} 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);
|
anode->u.external[0].length = cpu_to_le32(len);
|
||||||
mark_buffer_dirty(bh);
|
mark_buffer_dirty(bh);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
fnode->ea_anode = 1;
|
fnode->flags |= FNODE_anode;
|
||||||
fnode->ea_secno = cpu_to_le32(a_s);*/
|
fnode->ea_secno = cpu_to_le32(a_s);*/
|
||||||
secno new_sec;
|
secno new_sec;
|
||||||
int i;
|
int i;
|
||||||
|
@ -338,7 +338,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||||
len = (pos + 511) >> 9;
|
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),
|
if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
|
||||||
0, len) != -1) {
|
0, len) != -1) {
|
||||||
len++;
|
len++;
|
||||||
|
@ -351,16 +351,16 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
|
||||||
h[1] = strlen(key);
|
h[1] = strlen(key);
|
||||||
h[2] = size & 0xff;
|
h[2] = size & 0xff;
|
||||||
h[3] = size >> 8;
|
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_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->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_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->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) + 5 + h[1], size, data)) goto bail;
|
||||||
fnode->ea_size_l = cpu_to_le32(pos);
|
fnode->ea_size_l = cpu_to_le32(pos);
|
||||||
ret:
|
ret:
|
||||||
hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
|
hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
|
||||||
return;
|
return;
|
||||||
bail:
|
bail:
|
||||||
if (le32_to_cpu(fnode->ea_secno))
|
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 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);
|
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_rootdir_entries[2];
|
||||||
u8 n_sectors_s[2];
|
u8 n_sectors_s[2];
|
||||||
u8 media_byte;
|
u8 media_byte;
|
||||||
u16 sectors_per_fat;
|
__le16 sectors_per_fat;
|
||||||
u16 sectors_per_track;
|
__le16 sectors_per_track;
|
||||||
u16 heads_per_cyl;
|
__le16 heads_per_cyl;
|
||||||
u32 n_hidden_sectors;
|
__le32 n_hidden_sectors;
|
||||||
u32 n_sectors_l; /* size of partition */
|
__le32 n_sectors_l; /* size of partition */
|
||||||
u8 drive_number;
|
u8 drive_number;
|
||||||
u8 mbz;
|
u8 mbz;
|
||||||
u8 sig_28h; /* 28h */
|
u8 sig_28h; /* 28h */
|
||||||
|
@ -63,7 +63,7 @@ struct hpfs_boot_block
|
||||||
u8 vol_label[11];
|
u8 vol_label[11];
|
||||||
u8 sig_hpfs[8]; /* "HPFS " */
|
u8 sig_hpfs[8]; /* "HPFS " */
|
||||||
u8 pad[448];
|
u8 pad[448];
|
||||||
u16 magic; /* aa55 */
|
__le16 magic; /* aa55 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,28 +75,28 @@ struct hpfs_boot_block
|
||||||
|
|
||||||
struct hpfs_super_block
|
struct hpfs_super_block
|
||||||
{
|
{
|
||||||
u32 magic; /* f995 e849 */
|
__le32 magic; /* f995 e849 */
|
||||||
u32 magic1; /* fa53 e9c5, more magic? */
|
__le32 magic1; /* fa53 e9c5, more magic? */
|
||||||
u8 version; /* version of a filesystem usually 2 */
|
u8 version; /* version of a filesystem usually 2 */
|
||||||
u8 funcversion; /* functional version - oldest version
|
u8 funcversion; /* functional version - oldest version
|
||||||
of filesystem that can understand
|
of filesystem that can understand
|
||||||
this disk */
|
this disk */
|
||||||
u16 zero; /* 0 */
|
__le16 zero; /* 0 */
|
||||||
fnode_secno root; /* fnode of root directory */
|
__le32 root; /* fnode of root directory */
|
||||||
secno n_sectors; /* size of filesystem */
|
__le32 n_sectors; /* size of filesystem */
|
||||||
u32 n_badblocks; /* number of bad blocks */
|
__le32 n_badblocks; /* number of bad blocks */
|
||||||
secno bitmaps; /* pointers to free space bit maps */
|
__le32 bitmaps; /* pointers to free space bit maps */
|
||||||
u32 zero1; /* 0 */
|
__le32 zero1; /* 0 */
|
||||||
secno badblocks; /* bad block list */
|
__le32 badblocks; /* bad block list */
|
||||||
u32 zero3; /* 0 */
|
__le32 zero3; /* 0 */
|
||||||
time32_t last_chkdsk; /* date last checked, 0 if never */
|
__le32 last_chkdsk; /* date last checked, 0 if never */
|
||||||
time32_t last_optimize; /* date last optimized, 0 if never */
|
__le32 last_optimize; /* date last optimized, 0 if never */
|
||||||
secno n_dir_band; /* number of sectors in dir band */
|
__le32 n_dir_band; /* number of sectors in dir band */
|
||||||
secno dir_band_start; /* first sector in dir band */
|
__le32 dir_band_start; /* first sector in dir band */
|
||||||
secno dir_band_end; /* last sector in dir band */
|
__le32 dir_band_end; /* last sector in dir band */
|
||||||
secno dir_band_bitmap; /* free space map, 1 dnode per bit */
|
__le32 dir_band_bitmap; /* free space map, 1 dnode per bit */
|
||||||
u8 volume_name[32]; /* not used */
|
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 */
|
u32 zero6[103]; /* 0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -109,8 +109,8 @@ struct hpfs_super_block
|
||||||
|
|
||||||
struct hpfs_spare_block
|
struct hpfs_spare_block
|
||||||
{
|
{
|
||||||
u32 magic; /* f991 1849 */
|
__le32 magic; /* f991 1849 */
|
||||||
u32 magic1; /* fa52 29c5, more magic? */
|
__le32 magic1; /* fa52 29c5, more magic? */
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN
|
#ifdef __LITTLE_ENDIAN
|
||||||
u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
|
u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
|
||||||
|
@ -153,21 +153,21 @@ struct hpfs_spare_block
|
||||||
u8 mm_contlgulty;
|
u8 mm_contlgulty;
|
||||||
u8 unused;
|
u8 unused;
|
||||||
|
|
||||||
secno hotfix_map; /* info about remapped bad sectors */
|
__le32 hotfix_map; /* info about remapped bad sectors */
|
||||||
u32 n_spares_used; /* number of hotfixes */
|
__le32 n_spares_used; /* number of hotfixes */
|
||||||
u32 n_spares; /* number of spares in hotfix map */
|
__le32 n_spares; /* number of spares in hotfix map */
|
||||||
u32 n_dnode_spares_free; /* spare dnodes unused */
|
__le32 n_dnode_spares_free; /* spare dnodes unused */
|
||||||
u32 n_dnode_spares; /* length of spare_dnodes[] list,
|
__le32 n_dnode_spares; /* length of spare_dnodes[] list,
|
||||||
follows in this block*/
|
follows in this block*/
|
||||||
secno code_page_dir; /* code page directory block */
|
__le32 code_page_dir; /* code page directory block */
|
||||||
u32 n_code_pages; /* number of code pages */
|
__le32 n_code_pages; /* number of code pages */
|
||||||
u32 super_crc; /* on HPFS386 and LAN Server this is
|
__le32 super_crc; /* on HPFS386 and LAN Server this is
|
||||||
checksum of superblock, on normal
|
checksum of superblock, on normal
|
||||||
OS/2 unused */
|
OS/2 unused */
|
||||||
u32 spare_crc; /* on HPFS386 checksum of spareblock */
|
__le32 spare_crc; /* on HPFS386 checksum of spareblock */
|
||||||
u32 zero1[15]; /* unused */
|
__le32 zero1[15]; /* unused */
|
||||||
dnode_secno spare_dnodes[100]; /* emergency free dnode list */
|
__le32 spare_dnodes[100]; /* emergency free dnode list */
|
||||||
u32 zero2[1]; /* room for more? */
|
__le32 zero2[1]; /* room for more? */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The bad block list is 4 sectors long. The first word must be zero,
|
/* 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
|
struct code_page_directory
|
||||||
{
|
{
|
||||||
u32 magic; /* 4945 21f7 */
|
__le32 magic; /* 4945 21f7 */
|
||||||
u32 n_code_pages; /* number of pointers following */
|
__le32 n_code_pages; /* number of pointers following */
|
||||||
u32 zero1[2];
|
__le32 zero1[2];
|
||||||
struct {
|
struct {
|
||||||
u16 ix; /* index */
|
__le16 ix; /* index */
|
||||||
u16 code_page_number; /* code page number */
|
__le16 code_page_number; /* code page number */
|
||||||
u32 bounds; /* matches corresponding word
|
__le32 bounds; /* matches corresponding word
|
||||||
in data block */
|
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 */
|
containing c.p. array */
|
||||||
u16 index; /* index in c.p. array in that sector*/
|
__le16 index; /* index in c.p. array in that sector*/
|
||||||
u16 unknown; /* some unknown value; usually 0;
|
__le16 unknown; /* some unknown value; usually 0;
|
||||||
2 in Japanese version */
|
2 in Japanese version */
|
||||||
} array[31]; /* unknown length */
|
} array[31]; /* unknown length */
|
||||||
};
|
};
|
||||||
|
@ -224,19 +224,19 @@ struct code_page_directory
|
||||||
|
|
||||||
struct code_page_data
|
struct code_page_data
|
||||||
{
|
{
|
||||||
u32 magic; /* 8945 21f7 */
|
__le32 magic; /* 8945 21f7 */
|
||||||
u32 n_used; /* # elements used in c_p_data[] */
|
__le32 n_used; /* # elements used in c_p_data[] */
|
||||||
u32 bounds[3]; /* looks a bit like
|
__le32 bounds[3]; /* looks a bit like
|
||||||
(beg1,end1), (beg2,end2)
|
(beg1,end1), (beg2,end2)
|
||||||
one byte each */
|
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] */
|
to start of c_p_data[ix] */
|
||||||
struct {
|
struct {
|
||||||
u16 ix; /* index */
|
__le16 ix; /* index */
|
||||||
u16 code_page_number; /* code page number */
|
__le16 code_page_number; /* code page number */
|
||||||
u16 unknown; /* the same as in cp directory */
|
__le16 unknown; /* the same as in cp directory */
|
||||||
u8 map[128]; /* upcase table for chars 80..ff */
|
u8 map[128]; /* upcase table for chars 80..ff */
|
||||||
u16 zero2;
|
__le16 zero2;
|
||||||
} code_page[3];
|
} code_page[3];
|
||||||
u8 incognita[78];
|
u8 incognita[78];
|
||||||
};
|
};
|
||||||
|
@ -278,8 +278,8 @@ struct code_page_data
|
||||||
#define DNODE_MAGIC 0x77e40aae
|
#define DNODE_MAGIC 0x77e40aae
|
||||||
|
|
||||||
struct dnode {
|
struct dnode {
|
||||||
u32 magic; /* 77e4 0aae */
|
__le32 magic; /* 77e4 0aae */
|
||||||
u32 first_free; /* offset from start of dnode to
|
__le32 first_free; /* offset from start of dnode to
|
||||||
first free dir entry */
|
first free dir entry */
|
||||||
#ifdef __LITTLE_ENDIAN
|
#ifdef __LITTLE_ENDIAN
|
||||||
u8 root_dnode: 1; /* Is it root dnode? */
|
u8 root_dnode: 1; /* Is it root dnode? */
|
||||||
|
@ -293,14 +293,14 @@ struct dnode {
|
||||||
u8 root_dnode: 1; /* Is it root dnode? */
|
u8 root_dnode: 1; /* Is it root dnode? */
|
||||||
#endif
|
#endif
|
||||||
u8 increment_me2[3];
|
u8 increment_me2[3];
|
||||||
secno up; /* (root dnode) directory's fnode
|
__le32 up; /* (root dnode) directory's fnode
|
||||||
(nonroot) parent dnode */
|
(nonroot) parent dnode */
|
||||||
dnode_secno self; /* pointer to this dnode */
|
__le32 self; /* pointer to this dnode */
|
||||||
u8 dirent[2028]; /* one or more dirents */
|
u8 dirent[2028]; /* one or more dirents */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hpfs_dirent {
|
struct hpfs_dirent {
|
||||||
u16 length; /* offset to next dirent */
|
__le16 length; /* offset to next dirent */
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN
|
#ifdef __LITTLE_ENDIAN
|
||||||
u8 first: 1; /* set on phony ^A^A (".") entry */
|
u8 first: 1; /* set on phony ^A^A (".") entry */
|
||||||
|
@ -346,12 +346,12 @@ struct hpfs_dirent {
|
||||||
u8 read_only: 1; /* dos attrib */
|
u8 read_only: 1; /* dos attrib */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fnode_secno fnode; /* fnode giving allocation info */
|
__le32 fnode; /* fnode giving allocation info */
|
||||||
time32_t write_date; /* mtime */
|
__le32 write_date; /* mtime */
|
||||||
u32 file_size; /* file length, bytes */
|
__le32 file_size; /* file length, bytes */
|
||||||
time32_t read_date; /* atime */
|
__le32 read_date; /* atime */
|
||||||
time32_t creation_date; /* ctime */
|
__le32 creation_date; /* ctime */
|
||||||
u32 ea_size; /* total EA length, bytes */
|
__le32 ea_size; /* total EA length, bytes */
|
||||||
u8 no_of_acls; /* number of ACL's (low 3 bits) */
|
u8 no_of_acls; /* number of ACL's (low 3 bits) */
|
||||||
u8 ix; /* code page index (of filename), see
|
u8 ix; /* code page index (of filename), see
|
||||||
struct code_page_data */
|
struct code_page_data */
|
||||||
|
@ -375,50 +375,36 @@ struct hpfs_dirent {
|
||||||
|
|
||||||
struct bplus_leaf_node
|
struct bplus_leaf_node
|
||||||
{
|
{
|
||||||
u32 file_secno; /* first file sector in extent */
|
__le32 file_secno; /* first file sector in extent */
|
||||||
u32 length; /* length, sectors */
|
__le32 length; /* length, sectors */
|
||||||
secno disk_secno; /* first corresponding disk sector */
|
__le32 disk_secno; /* first corresponding disk sector */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bplus_internal_node
|
struct bplus_internal_node
|
||||||
{
|
{
|
||||||
u32 file_secno; /* subtree maps sectors < this */
|
__le32 file_secno; /* subtree maps sectors < this */
|
||||||
anode_secno down; /* pointer to subtree */
|
__le32 down; /* pointer to subtree */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BP_hbff = 1,
|
||||||
|
BP_fnode_parent = 0x20,
|
||||||
|
BP_binary_search = 0x40,
|
||||||
|
BP_internal = 0x80
|
||||||
|
};
|
||||||
struct bplus_header
|
struct bplus_header
|
||||||
{
|
{
|
||||||
#ifdef __LITTLE_ENDIAN
|
u8 flags; /* bit 0 - high bit of first free entry offset
|
||||||
u8 hbff: 1; /* high bit of first free entry offset */
|
bit 5 - we're pointed to by an fnode,
|
||||||
u8 flag1234: 4;
|
|
||||||
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
|
|
||||||
the data btree or some ea or the
|
the data btree or some ea or the
|
||||||
main ea bootage pointer ea_secno */
|
main ea bootage pointer ea_secno
|
||||||
/* also can get set in fnodes, which
|
bit 6 - suggest binary search (unused)
|
||||||
may be a chkdsk glitch or may mean
|
bit 7 - 1 -> (internal) tree of anodes
|
||||||
this bit is irrelevant in fnodes,
|
0 -> (leaf) list of extents */
|
||||||
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
|
|
||||||
u8 fill[3];
|
u8 fill[3];
|
||||||
u8 n_free_nodes; /* free nodes in following array */
|
u8 n_free_nodes; /* free nodes in following array */
|
||||||
u8 n_used_nodes; /* used 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 */
|
first free node in array */
|
||||||
union {
|
union {
|
||||||
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
|
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
|
||||||
|
@ -428,6 +414,16 @@ struct bplus_header
|
||||||
} u;
|
} 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 */
|
/* fnode: root of allocation b+ tree, and EA's */
|
||||||
|
|
||||||
/* Every file and every directory has one fnode, pointed to by the directory
|
/* Every file and every directory has one fnode, pointed to by the directory
|
||||||
|
@ -436,62 +432,56 @@ struct bplus_header
|
||||||
|
|
||||||
#define FNODE_MAGIC 0xf7e40aae
|
#define FNODE_MAGIC 0xf7e40aae
|
||||||
|
|
||||||
|
enum {FNODE_anode = cpu_to_le16(2), FNODE_dir = cpu_to_le16(256)};
|
||||||
struct fnode
|
struct fnode
|
||||||
{
|
{
|
||||||
u32 magic; /* f7e4 0aae */
|
__le32 magic; /* f7e4 0aae */
|
||||||
u32 zero1[2]; /* read history */
|
__le32 zero1[2]; /* read history */
|
||||||
u8 len, name[15]; /* true length, truncated name */
|
u8 len, name[15]; /* true length, truncated name */
|
||||||
fnode_secno up; /* pointer to file's directory fnode */
|
__le32 up; /* pointer to file's directory fnode */
|
||||||
secno acl_size_l;
|
__le32 acl_size_l;
|
||||||
secno acl_secno;
|
__le32 acl_secno;
|
||||||
u16 acl_size_s;
|
__le16 acl_size_s;
|
||||||
u8 acl_anode;
|
u8 acl_anode;
|
||||||
u8 zero2; /* history bit count */
|
u8 zero2; /* history bit count */
|
||||||
u32 ea_size_l; /* length of disk-resident ea's */
|
__le32 ea_size_l; /* length of disk-resident ea's */
|
||||||
secno ea_secno; /* first sector of disk-resident ea's*/
|
__le32 ea_secno; /* first sector of disk-resident ea's*/
|
||||||
u16 ea_size_s; /* length of fnode-resident ea's */
|
__le16 ea_size_s; /* length of fnode-resident ea's */
|
||||||
|
|
||||||
#ifdef __LITTLE_ENDIAN
|
__le16 flags; /* bit 1 set -> ea_secno is an anode */
|
||||||
u8 flag0: 1;
|
/* bit 8 set -> directory. first & only extent
|
||||||
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
|
|
||||||
points to dnode. */
|
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 */
|
struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */
|
||||||
union {
|
union {
|
||||||
struct bplus_leaf_node external[8];
|
struct bplus_leaf_node external[8];
|
||||||
struct bplus_internal_node internal[12];
|
struct bplus_internal_node internal[12];
|
||||||
} u;
|
} u;
|
||||||
|
|
||||||
u32 file_size; /* file length, bytes */
|
__le32 file_size; /* file length, bytes */
|
||||||
u32 n_needea; /* number of EA's with NEEDEA set */
|
__le32 n_needea; /* number of EA's with NEEDEA set */
|
||||||
u8 user_id[16]; /* unused */
|
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 */
|
to first fnode-resident ea */
|
||||||
u8 dasd_limit_treshhold;
|
u8 dasd_limit_treshhold;
|
||||||
u8 dasd_limit_delta;
|
u8 dasd_limit_delta;
|
||||||
u32 dasd_limit;
|
__le32 dasd_limit;
|
||||||
u32 dasd_usage;
|
__le32 dasd_usage;
|
||||||
u8 ea[316]; /* zero or more EA's, packed together
|
u8 ea[316]; /* zero or more EA's, packed together
|
||||||
with no alignment padding.
|
with no alignment padding.
|
||||||
(Do not use this name, get here
|
(Do not use this name, get here
|
||||||
via fnode + ea_offs. I think.) */
|
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 */
|
/* anode: 99.44% pure allocation tree */
|
||||||
|
|
||||||
|
@ -499,9 +489,9 @@ struct fnode
|
||||||
|
|
||||||
struct anode
|
struct anode
|
||||||
{
|
{
|
||||||
u32 magic; /* 37e4 0aae */
|
__le32 magic; /* 37e4 0aae */
|
||||||
anode_secno self; /* pointer to this anode */
|
__le32 self; /* pointer to this anode */
|
||||||
secno up; /* parent anode or fnode */
|
__le32 up; /* parent anode or fnode */
|
||||||
|
|
||||||
struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */
|
struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */
|
||||||
union {
|
union {
|
||||||
|
@ -509,7 +499,7 @@ struct anode
|
||||||
struct bplus_internal_node internal[60];
|
struct bplus_internal_node internal[60];
|
||||||
} u;
|
} 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
|
run, or in multiple runs. Flags in the fnode tell whether the EA list
|
||||||
is immediate, in a single run, or in multiple runs. */
|
is immediate, in a single run, or in multiple runs. */
|
||||||
|
|
||||||
|
enum {EA_indirect = 1, EA_anode = 2, EA_needea = 128 };
|
||||||
struct extended_attribute
|
struct extended_attribute
|
||||||
{
|
{
|
||||||
#ifdef __LITTLE_ENDIAN
|
u8 flags; /* bit 0 set -> value gives sector number
|
||||||
u8 indirect: 1; /* 1 -> value gives sector number
|
|
||||||
where real value starts */
|
where real value starts */
|
||||||
u8 anode: 1; /* 1 -> sector is an anode
|
/* bit 1 set -> sector is an anode
|
||||||
that points to fragmented value */
|
that points to fragmented value */
|
||||||
u8 flag23456: 5;
|
/* bit 7 set -> required ea */
|
||||||
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
|
|
||||||
u8 namelen; /* length of name, bytes */
|
u8 namelen; /* length of name, bytes */
|
||||||
u8 valuelen_lo; /* length of value, bytes */
|
u8 valuelen_lo; /* length of value, bytes */
|
||||||
u8 valuelen_hi; /* length of value, bytes */
|
u8 valuelen_hi; /* length of value, bytes */
|
||||||
u8 name[0];
|
u8 name[];
|
||||||
/*
|
/*
|
||||||
u8 name[namelen]; ascii attrib name
|
u8 name[namelen]; ascii attrib name
|
||||||
u8 nul; terminating '\0', not counted
|
u8 nul; terminating '\0', not counted
|
||||||
u8 value[valuelen]; value, arbitrary
|
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
|
u32 length; real length of value, bytes
|
||||||
secno secno; sector address where it starts
|
secno secno; sector address where it starts
|
||||||
if this.anode, the above sector number is the root of an anode tree
|
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:
|
Local Variables:
|
||||||
comment-column: 40
|
comment-column: 40
|
||||||
|
|
|
@ -75,7 +75,7 @@ struct hpfs_sb_info {
|
||||||
unsigned char *sb_cp_table; /* code page tables: */
|
unsigned char *sb_cp_table; /* code page tables: */
|
||||||
/* 128 bytes uppercasing table & */
|
/* 128 bytes uppercasing table & */
|
||||||
/* 128 bytes lowercasing 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_c_bitmap; /* current bitmap */
|
||||||
unsigned sb_max_fwd_alloc; /* max forwad allocation */
|
unsigned sb_max_fwd_alloc; /* max forwad allocation */
|
||||||
int sb_timeshift;
|
int sb_timeshift;
|
||||||
|
@ -93,7 +93,7 @@ struct quad_buffer_head {
|
||||||
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
|
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
|
||||||
{
|
{
|
||||||
CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
|
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 */
|
/* 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)
|
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)
|
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)
|
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;
|
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;
|
int i;
|
||||||
if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
|
if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
|
||||||
|
@ -268,10 +268,10 @@ void hpfs_evict_inode(struct inode *);
|
||||||
|
|
||||||
/* map.c */
|
/* map.c */
|
||||||
|
|
||||||
unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
|
__le32 *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_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
|
||||||
unsigned char *hpfs_load_code_page(struct super_block *, secno);
|
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 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 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 *);
|
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;
|
int n_dnodes, n_subdirs;
|
||||||
i->i_mode |= S_IFDIR;
|
i->i_mode |= S_IFDIR;
|
||||||
i->i_op = &hpfs_dir_iops;
|
i->i_op = &hpfs_dir_iops;
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
|
|
||||||
#include "hpfs_fn.h"
|
#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);
|
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)
|
struct quad_buffer_head *qbh, char *id)
|
||||||
{
|
{
|
||||||
secno sec;
|
secno sec;
|
||||||
|
@ -89,18 +89,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
|
||||||
return cp_table;
|
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;
|
struct buffer_head *bh;
|
||||||
int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
|
int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
|
||||||
int i;
|
int i;
|
||||||
secno *b;
|
__le32 *b;
|
||||||
if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
|
if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
|
||||||
printk("HPFS: can't allocate memory for bitmap directory\n");
|
printk("HPFS: can't allocate memory for bitmap directory\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (i=0;i<n;i++) {
|
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) {
|
if (!d) {
|
||||||
kfree(b);
|
kfree(b);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -130,16 +130,16 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
|
||||||
(unsigned long)ino);
|
(unsigned long)ino);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (!fnode->dirflag) {
|
if (!fnode_is_dir(fnode)) {
|
||||||
if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
|
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,
|
hpfs_error(s,
|
||||||
"bad number of nodes in fnode %08lx",
|
"bad number of nodes in fnode %08lx",
|
||||||
(unsigned long)ino);
|
(unsigned long)ino);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (le16_to_cpu(fnode->btree.first_free) !=
|
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,
|
hpfs_error(s,
|
||||||
"bad first_free pointer in fnode %08lx",
|
"bad first_free pointer in fnode %08lx",
|
||||||
(unsigned long)ino);
|
(unsigned long)ino);
|
||||||
|
@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
|
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);
|
hpfs_error(s, "bad number of nodes in anode %08x", ano);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
if (le16_to_cpu(anode->btree.first_free) !=
|
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);
|
hpfs_error(s, "bad first_free pointer in anode %08x", ano);
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
|
||||||
fnode->len = len;
|
fnode->len = len;
|
||||||
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
memcpy(fnode->name, name, len > 15 ? 15 : len);
|
||||||
fnode->up = cpu_to_le32(dir->i_ino);
|
fnode->up = cpu_to_le32(dir->i_ino);
|
||||||
fnode->dirflag = 1;
|
fnode->flags |= FNODE_dir;
|
||||||
fnode->btree.n_free_nodes = 7;
|
fnode->btree.n_free_nodes = 7;
|
||||||
fnode->btree.n_used_nodes = 1;
|
fnode->btree.n_used_nodes = 1;
|
||||||
fnode->btree.first_free = cpu_to_le16(0x14);
|
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);
|
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) {
|
if (errs >= 2) {
|
||||||
printk("HPFS: Hotfixes not supported here, try chkdsk\n");
|
printk("HPFS: Hotfixes not supported here, try chkdsk\n");
|
||||||
mark_dirty(s, 0);
|
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_mtime.tv_nsec = 0;
|
||||||
root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
|
root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
|
||||||
root->i_ctime.tv_nsec = 0;
|
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;
|
hpfs_i(root)->i_parent_dir = root->i_ino;
|
||||||
if (root->i_size == -1)
|
if (root->i_size == -1)
|
||||||
root->i_size = 2048;
|
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;
|
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
|
* touch_atime - update the access time
|
||||||
* @mnt: mount the inode is accessed on
|
* @path: the &struct path to update
|
||||||
* @dentry: dentry accessed
|
|
||||||
*
|
*
|
||||||
* Update the accessed time on an inode and mark it for writeback.
|
* Update the accessed time on an inode and mark it for writeback.
|
||||||
* This function automatically handles read only file systems and media,
|
* 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))
|
if (mnt_want_write(mnt))
|
||||||
return;
|
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);
|
mnt_drop_write(mnt);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(touch_atime);
|
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_update_time - update mtime and ctime time
|
||||||
* @file: file accessed
|
* @file: file accessed
|
||||||
|
@ -1540,18 +1631,20 @@ EXPORT_SYMBOL(touch_atime);
|
||||||
* usage in the file write path of filesystems, and filesystems may
|
* usage in the file write path of filesystems, and filesystems may
|
||||||
* choose to explicitly ignore update via this function with the
|
* choose to explicitly ignore update via this function with the
|
||||||
* S_NOCMTIME inode flag, e.g. for network filesystem where these
|
* 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 inode *inode = file->f_path.dentry->d_inode;
|
||||||
struct timespec now;
|
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 */
|
/* First try to exhaust all avenues to not sync */
|
||||||
if (IS_NOCMTIME(inode))
|
if (IS_NOCMTIME(inode))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
now = current_fs_time(inode->i_sb);
|
now = current_fs_time(inode->i_sb);
|
||||||
if (!timespec_equal(&inode->i_mtime, &now))
|
if (!timespec_equal(&inode->i_mtime, &now))
|
||||||
|
@ -1564,21 +1657,16 @@ void file_update_time(struct file *file)
|
||||||
sync_it |= S_VERSION;
|
sync_it |= S_VERSION;
|
||||||
|
|
||||||
if (!sync_it)
|
if (!sync_it)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
/* Finally allowed to write? Takes lock. */
|
/* Finally allowed to write? Takes lock. */
|
||||||
if (mnt_want_write_file(file))
|
if (mnt_want_write_file(file))
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
/* Only change inode inside the lock region */
|
ret = update_time(inode, &now, sync_it);
|
||||||
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);
|
|
||||||
mnt_drop_write_file(file);
|
mnt_drop_write_file(file);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(file_update_time);
|
EXPORT_SYMBOL(file_update_time);
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ extern int sb_prepare_remount_readonly(struct super_block *);
|
||||||
|
|
||||||
extern void __init mnt_init(void);
|
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,
|
extern long do_handle_open(int mountdirfd,
|
||||||
struct file_handle __user *ufh, int open_flag);
|
struct file_handle __user *ufh, int open_flag);
|
||||||
|
extern int open_check_o_direct(struct file *f);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* inode.c
|
* inode.c
|
||||||
|
|
|
@ -107,12 +107,11 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
isofs_export_encode_fh(struct dentry *dentry,
|
isofs_export_encode_fh(struct inode *inode,
|
||||||
__u32 *fh32,
|
__u32 *fh32,
|
||||||
int *max_len,
|
int *max_len,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct inode * inode = dentry->d_inode;
|
|
||||||
struct iso_inode_info * ei = ISOFS_I(inode);
|
struct iso_inode_info * ei = ISOFS_I(inode);
|
||||||
int len = *max_len;
|
int len = *max_len;
|
||||||
int type = 1;
|
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
|
* offset of the inode and the upper 16 bits of fh32[1] to
|
||||||
* hold the offset of the parent.
|
* hold the offset of the parent.
|
||||||
*/
|
*/
|
||||||
if (connectable && (len < 5)) {
|
if (parent && (len < 5)) {
|
||||||
*max_len = 5;
|
*max_len = 5;
|
||||||
return 255;
|
return 255;
|
||||||
} else if (len < 3) {
|
} else if (len < 3) {
|
||||||
|
@ -136,16 +135,12 @@ isofs_export_encode_fh(struct dentry *dentry,
|
||||||
fh32[0] = ei->i_iget5_block;
|
fh32[0] = ei->i_iget5_block;
|
||||||
fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
|
fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
|
||||||
fh32[2] = inode->i_generation;
|
fh32[2] = inode->i_generation;
|
||||||
if (connectable && !S_ISDIR(inode->i_mode)) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
struct iso_inode_info *eparent;
|
struct iso_inode_info *eparent;
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
parent = dentry->d_parent->d_inode;
|
|
||||||
eparent = ISOFS_I(parent);
|
eparent = ISOFS_I(parent);
|
||||||
fh32[3] = eparent->i_iget5_block;
|
fh32[3] = eparent->i_iget5_block;
|
||||||
fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
|
fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
|
||||||
fh32[4] = parent->i_generation;
|
fh32[4] = parent->i_generation;
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
len = 5;
|
len = 5;
|
||||||
type = 2;
|
type = 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,10 @@ struct jffs2_sb_info {
|
||||||
struct jffs2_inodirty *wbuf_inodes;
|
struct jffs2_inodirty *wbuf_inodes;
|
||||||
struct rw_semaphore wbuf_sem; /* Protects the write buffer */
|
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;
|
unsigned char *oobbuf;
|
||||||
int oobavail; /* How many bytes are available for JFFS2 in OOB */
|
int oobavail; /* How many bytes are available for JFFS2 in OOB */
|
||||||
#endif
|
#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(c) (0)
|
||||||
#define jffs2_ubivol_setup(c) (0)
|
#define jffs2_ubivol_setup(c) (0)
|
||||||
#define jffs2_ubivol_cleanup(c) do {} while (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 */
|
#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))
|
#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);
|
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
|
||||||
void jffs2_nor_wbuf_flash_cleanup(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 */
|
#endif /* WRITEBUFFER */
|
||||||
|
|
||||||
static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c)
|
|
||||||
{
|
|
||||||
OFNI_BS_2SFFJ(c)->s_dirt = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* background.c */
|
/* background.c */
|
||||||
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
||||||
void jffs2_stop_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);
|
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)
|
static const char *jffs2_compr_name(unsigned int compr)
|
||||||
{
|
{
|
||||||
switch (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);
|
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
|
||||||
|
|
||||||
jffs2_write_super(sb);
|
|
||||||
|
|
||||||
mutex_lock(&c->alloc_sem);
|
mutex_lock(&c->alloc_sem);
|
||||||
jffs2_flush_wbuf_pad(c);
|
jffs2_flush_wbuf_pad(c);
|
||||||
mutex_unlock(&c->alloc_sem);
|
mutex_unlock(&c->alloc_sem);
|
||||||
|
@ -251,7 +234,6 @@ static const struct super_operations jffs2_super_operations =
|
||||||
.alloc_inode = jffs2_alloc_inode,
|
.alloc_inode = jffs2_alloc_inode,
|
||||||
.destroy_inode =jffs2_destroy_inode,
|
.destroy_inode =jffs2_destroy_inode,
|
||||||
.put_super = jffs2_put_super,
|
.put_super = jffs2_put_super,
|
||||||
.write_super = jffs2_write_super,
|
|
||||||
.statfs = jffs2_statfs,
|
.statfs = jffs2_statfs,
|
||||||
.remount_fs = jffs2_remount_fs,
|
.remount_fs = jffs2_remount_fs,
|
||||||
.evict_inode = jffs2_evict_inode,
|
.evict_inode = jffs2_evict_inode,
|
||||||
|
@ -319,9 +301,6 @@ static void jffs2_put_super (struct super_block *sb)
|
||||||
|
|
||||||
jffs2_dbg(2, "%s()\n", __func__);
|
jffs2_dbg(2, "%s()\n", __func__);
|
||||||
|
|
||||||
if (sb->s_dirt)
|
|
||||||
jffs2_write_super(sb);
|
|
||||||
|
|
||||||
mutex_lock(&c->alloc_sem);
|
mutex_lock(&c->alloc_sem);
|
||||||
jffs2_flush_wbuf_pad(c);
|
jffs2_flush_wbuf_pad(c);
|
||||||
mutex_unlock(&c->alloc_sem);
|
mutex_unlock(&c->alloc_sem);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <linux/mtd/nand.h>
|
#include <linux/mtd/nand.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/writeback.h>
|
||||||
|
|
||||||
#include "nodelist.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;
|
struct jffs2_inodirty *new;
|
||||||
|
|
||||||
/* Mark the superblock dirty so that kupdated will flush... */
|
/* Schedule delayed write-buffer write-out */
|
||||||
jffs2_dirty_trigger(c);
|
jffs2_dirty_trigger(c);
|
||||||
|
|
||||||
if (jffs2_wbuf_pending_for_ino(c, ino))
|
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;
|
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)
|
int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
||||||
{
|
{
|
||||||
struct nand_ecclayout *oinfo = c->mtd->ecclayout;
|
struct nand_ecclayout *oinfo = c->mtd->ecclayout;
|
||||||
|
@ -1169,6 +1211,8 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
|
||||||
|
|
||||||
/* Initialise write buffer */
|
/* Initialise write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
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_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
@ -1207,8 +1251,8 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
|
||||||
|
|
||||||
/* Initialize write buffer */
|
/* Initialize write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
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;
|
c->wbuf_pagesize = c->mtd->erasesize;
|
||||||
|
|
||||||
/* Find a suitable c->sector_size
|
/* Find a suitable c->sector_size
|
||||||
|
@ -1267,6 +1311,9 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
|
||||||
|
|
||||||
/* Initialize write buffer */
|
/* Initialize write buffer */
|
||||||
init_rwsem(&c->wbuf_sem);
|
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_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
@ -1299,6 +1346,8 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
init_rwsem(&c->wbuf_sem);
|
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_pagesize = c->mtd->writesize;
|
||||||
c->wbuf_ofs = 0xFFFFFFFF;
|
c->wbuf_ofs = 0xFFFFFFFF;
|
||||||
|
|
|
@ -1636,12 +1636,13 @@ EXPORT_SYMBOL(flock_lock_file_wait);
|
||||||
SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
||||||
{
|
{
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
|
int fput_needed;
|
||||||
struct file_lock *lock;
|
struct file_lock *lock;
|
||||||
int can_sleep, unlock;
|
int can_sleep, unlock;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EBADF;
|
error = -EBADF;
|
||||||
filp = fget(fd);
|
filp = fget_light(fd, &fput_needed);
|
||||||
if (!filp)
|
if (!filp)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -1674,7 +1675,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
|
||||||
locks_free_lock(lock);
|
locks_free_lock(lock);
|
||||||
|
|
||||||
out_putf:
|
out_putf:
|
||||||
fput(filp);
|
fput_light(filp, fput_needed);
|
||||||
out:
|
out:
|
||||||
return error;
|
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);
|
mntget(nd->path.mnt);
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
nd->flags &= ~LOOKUP_RCU;
|
nd->flags &= ~LOOKUP_RCU;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -507,14 +507,14 @@ static int complete_walk(struct nameidata *nd)
|
||||||
if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
|
if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return -ECHILD;
|
return -ECHILD;
|
||||||
}
|
}
|
||||||
BUG_ON(nd->inode != dentry->d_inode);
|
BUG_ON(nd->inode != dentry->d_inode);
|
||||||
spin_unlock(&dentry->d_lock);
|
spin_unlock(&dentry->d_lock);
|
||||||
mntget(nd->path.mnt);
|
mntget(nd->path.mnt);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (likely(!(nd->flags & LOOKUP_JUMPED)))
|
if (likely(!(nd->flags & LOOKUP_JUMPED)))
|
||||||
|
@ -681,15 +681,15 @@ int follow_up(struct path *path)
|
||||||
struct mount *parent;
|
struct mount *parent;
|
||||||
struct dentry *mountpoint;
|
struct dentry *mountpoint;
|
||||||
|
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
parent = mnt->mnt_parent;
|
parent = mnt->mnt_parent;
|
||||||
if (&parent->mnt == path->mnt) {
|
if (&parent->mnt == path->mnt) {
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
mntget(&parent->mnt);
|
mntget(&parent->mnt);
|
||||||
mountpoint = dget(mnt->mnt_mountpoint);
|
mountpoint = dget(mnt->mnt_mountpoint);
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
dput(path->dentry);
|
dput(path->dentry);
|
||||||
path->dentry = mountpoint;
|
path->dentry = mountpoint;
|
||||||
mntput(path->mnt);
|
mntput(path->mnt);
|
||||||
|
@ -947,7 +947,7 @@ failed:
|
||||||
if (!(nd->flags & LOOKUP_ROOT))
|
if (!(nd->flags & LOOKUP_ROOT))
|
||||||
nd->root.mnt = NULL;
|
nd->root.mnt = NULL;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return -ECHILD;
|
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.
|
* small and for now I'd prefer to have fast path as straight as possible.
|
||||||
* It _is_ time-critical.
|
* It _is_ time-critical.
|
||||||
*/
|
*/
|
||||||
static int do_lookup(struct nameidata *nd, struct qstr *name,
|
static int lookup_fast(struct nameidata *nd, struct qstr *name,
|
||||||
struct path *path, struct inode **inode)
|
struct path *path, struct inode **inode)
|
||||||
{
|
{
|
||||||
struct vfsmount *mnt = nd->path.mnt;
|
struct vfsmount *mnt = nd->path.mnt;
|
||||||
struct dentry *dentry, *parent = nd->path.dentry;
|
struct dentry *dentry, *parent = nd->path.dentry;
|
||||||
|
@ -1208,7 +1208,7 @@ unlazy:
|
||||||
goto need_lookup;
|
goto need_lookup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
done:
|
|
||||||
path->mnt = mnt;
|
path->mnt = mnt;
|
||||||
path->dentry = dentry;
|
path->dentry = dentry;
|
||||||
err = follow_managed(path, nd->flags);
|
err = follow_managed(path, nd->flags);
|
||||||
|
@ -1222,6 +1222,17 @@ done:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
need_lookup:
|
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);
|
BUG_ON(nd->inode != parent->d_inode);
|
||||||
|
|
||||||
mutex_lock(&parent->d_inode->i_mutex);
|
mutex_lock(&parent->d_inode->i_mutex);
|
||||||
|
@ -1229,7 +1240,16 @@ need_lookup:
|
||||||
mutex_unlock(&parent->d_inode->i_mutex);
|
mutex_unlock(&parent->d_inode->i_mutex);
|
||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
return PTR_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)
|
static inline int may_lookup(struct nameidata *nd)
|
||||||
|
@ -1265,7 +1285,7 @@ static void terminate_walk(struct nameidata *nd)
|
||||||
if (!(nd->flags & LOOKUP_ROOT))
|
if (!(nd->flags & LOOKUP_ROOT))
|
||||||
nd->root.mnt = NULL;
|
nd->root.mnt = NULL;
|
||||||
rcu_read_unlock();
|
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))
|
if (unlikely(type != LAST_NORM))
|
||||||
return handle_dots(nd, type);
|
return handle_dots(nd, type);
|
||||||
err = do_lookup(nd, name, path, &inode);
|
err = lookup_fast(nd, name, path, &inode);
|
||||||
if (unlikely(err)) {
|
if (unlikely(err)) {
|
||||||
terminate_walk(nd);
|
if (err < 0)
|
||||||
return err;
|
goto out_err;
|
||||||
}
|
|
||||||
if (!inode) {
|
err = lookup_slow(nd, name, path);
|
||||||
path_to_nameidata(path, nd);
|
if (err < 0)
|
||||||
terminate_walk(nd);
|
goto out_err;
|
||||||
return -ENOENT;
|
|
||||||
|
inode = path->dentry->d_inode;
|
||||||
}
|
}
|
||||||
|
err = -ENOENT;
|
||||||
|
if (!inode)
|
||||||
|
goto out_path_put;
|
||||||
|
|
||||||
if (should_follow_link(inode, follow)) {
|
if (should_follow_link(inode, follow)) {
|
||||||
if (nd->flags & LOOKUP_RCU) {
|
if (nd->flags & LOOKUP_RCU) {
|
||||||
if (unlikely(unlazy_walk(nd, path->dentry))) {
|
if (unlikely(unlazy_walk(nd, path->dentry))) {
|
||||||
terminate_walk(nd);
|
err = -ECHILD;
|
||||||
return -ECHILD;
|
goto out_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BUG_ON(inode != path->dentry->d_inode);
|
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);
|
path_to_nameidata(path, nd);
|
||||||
nd->inode = inode;
|
nd->inode = inode;
|
||||||
return 0;
|
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->path = nd->root;
|
||||||
nd->inode = inode;
|
nd->inode = inode;
|
||||||
if (flags & LOOKUP_RCU) {
|
if (flags & LOOKUP_RCU) {
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1633,7 +1664,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
|
||||||
|
|
||||||
if (*name=='/') {
|
if (*name=='/') {
|
||||||
if (flags & LOOKUP_RCU) {
|
if (flags & LOOKUP_RCU) {
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
set_root_rcu(nd);
|
set_root_rcu(nd);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1646,7 +1677,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
|
||||||
struct fs_struct *fs = current->fs;
|
struct fs_struct *fs = current->fs;
|
||||||
unsigned seq;
|
unsigned seq;
|
||||||
|
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -1682,7 +1713,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
|
||||||
if (fput_needed)
|
if (fput_needed)
|
||||||
*fp = file;
|
*fp = file;
|
||||||
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
} else {
|
} else {
|
||||||
path_get(&file->f_path);
|
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 want_write = 0;
|
||||||
int acc_mode = op->acc_mode;
|
int acc_mode = op->acc_mode;
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
|
struct inode *inode;
|
||||||
|
int symlink_ok = 0;
|
||||||
|
struct path save_parent = { .dentry = NULL, .mnt = NULL };
|
||||||
|
bool retried = false;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
nd->flags &= ~LOOKUP_PARENT;
|
nd->flags &= ~LOOKUP_PARENT;
|
||||||
|
@ -2200,30 +2235,23 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(open_flag & O_CREAT)) {
|
if (!(open_flag & O_CREAT)) {
|
||||||
int symlink_ok = 0;
|
|
||||||
if (nd->last.name[nd->last.len])
|
if (nd->last.name[nd->last.len])
|
||||||
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
|
||||||
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
|
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
|
||||||
symlink_ok = 1;
|
symlink_ok = 1;
|
||||||
/* we _can_ be in RCU mode here */
|
/* we _can_ be in RCU mode here */
|
||||||
error = walk_component(nd, path, &nd->last, LAST_NORM,
|
error = lookup_fast(nd, &nd->last, path, &inode);
|
||||||
!symlink_ok);
|
if (unlikely(error)) {
|
||||||
if (error < 0)
|
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)
|
|
||||||
goto exit;
|
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 finish_lookup;
|
||||||
goto ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create side of things */
|
/* 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])
|
if (nd->last.name[nd->last.len])
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
retry_lookup:
|
||||||
mutex_lock(&dir->d_inode->i_mutex);
|
mutex_lock(&dir->d_inode->i_mutex);
|
||||||
|
|
||||||
dentry = lookup_hash(nd);
|
dentry = lookup_hash(nd);
|
||||||
|
@ -2302,22 +2331,49 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
||||||
if (error)
|
if (error)
|
||||||
nd->flags |= LOOKUP_JUMPED;
|
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;
|
error = -ENOENT;
|
||||||
if (!path->dentry->d_inode)
|
if (!inode) {
|
||||||
goto exit_dput;
|
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;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
path_to_nameidata(path, nd);
|
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
|
||||||
nd->inode = path->dentry->d_inode;
|
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... */
|
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
|
||||||
error = complete_walk(nd);
|
error = complete_walk(nd);
|
||||||
if (error)
|
if (error) {
|
||||||
|
path_put(&save_parent);
|
||||||
return ERR_PTR(error);
|
return ERR_PTR(error);
|
||||||
|
}
|
||||||
error = -EISDIR;
|
error = -EISDIR;
|
||||||
if (S_ISDIR(nd->inode->i_mode))
|
if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
error = -ENOTDIR;
|
||||||
|
if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
|
||||||
|
goto exit;
|
||||||
|
audit_inode(pathname, nd->path.dentry);
|
||||||
ok:
|
ok:
|
||||||
if (!S_ISREG(nd->inode->i_mode))
|
if (!S_ISREG(nd->inode->i_mode))
|
||||||
will_truncate = 0;
|
will_truncate = 0;
|
||||||
|
@ -2333,6 +2389,20 @@ common:
|
||||||
if (error)
|
if (error)
|
||||||
goto exit;
|
goto exit;
|
||||||
filp = nameidata_to_filp(nd);
|
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)) {
|
if (!IS_ERR(filp)) {
|
||||||
error = ima_file_check(filp, op->acc_mode);
|
error = ima_file_check(filp, op->acc_mode);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -2352,7 +2422,8 @@ common:
|
||||||
out:
|
out:
|
||||||
if (want_write)
|
if (want_write)
|
||||||
mnt_drop_write(nd->path.mnt);
|
mnt_drop_write(nd->path.mnt);
|
||||||
path_put(&nd->path);
|
path_put(&save_parent);
|
||||||
|
terminate_walk(nd);
|
||||||
return filp;
|
return filp;
|
||||||
|
|
||||||
exit_mutex_unlock:
|
exit_mutex_unlock:
|
||||||
|
@ -2415,6 +2486,12 @@ out:
|
||||||
if (base)
|
if (base)
|
||||||
fput(base);
|
fput(base);
|
||||||
release_open_intent(nd);
|
release_open_intent(nd);
|
||||||
|
if (filp == ERR_PTR(-EOPENSTALE)) {
|
||||||
|
if (flags & LOOKUP_RCU)
|
||||||
|
filp = ERR_PTR(-ECHILD);
|
||||||
|
else
|
||||||
|
filp = ERR_PTR(-ESTALE);
|
||||||
|
}
|
||||||
return filp;
|
return filp;
|
||||||
|
|
||||||
out_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;
|
int ret = 0;
|
||||||
|
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
|
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
|
||||||
/*
|
/*
|
||||||
* After storing MNT_WRITE_HOLD, we'll read the counters. This store
|
* 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();
|
smp_wmb();
|
||||||
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 ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __mnt_unmake_readonly(struct mount *mnt)
|
static void __mnt_unmake_readonly(struct mount *mnt)
|
||||||
{
|
{
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
mnt->mnt.mnt_flags &= ~MNT_READONLY;
|
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)
|
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))
|
if (atomic_long_read(&sb->s_remove_count))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
|
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
|
||||||
if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
|
if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
|
||||||
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
|
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)
|
if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
|
||||||
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -522,14 +522,14 @@ struct vfsmount *lookup_mnt(struct path *path)
|
||||||
{
|
{
|
||||||
struct mount *child_mnt;
|
struct mount *child_mnt;
|
||||||
|
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
|
child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
|
||||||
if (child_mnt) {
|
if (child_mnt) {
|
||||||
mnt_add_count(child_mnt, 1);
|
mnt_add_count(child_mnt, 1);
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return &child_mnt->mnt;
|
return &child_mnt->mnt;
|
||||||
} else {
|
} else {
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return NULL;
|
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.mnt_sb = root->d_sb;
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
mnt->mnt_parent = mnt;
|
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);
|
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
return &mnt->mnt;
|
return &mnt->mnt;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(vfs_kern_mount);
|
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.mnt_root = dget(root);
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
mnt->mnt_parent = mnt;
|
mnt->mnt_parent = mnt;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
|
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
if (flag & CL_SLAVE) {
|
if (flag & CL_SLAVE) {
|
||||||
list_add(&mnt->mnt_slave, &old->mnt_slave_list);
|
list_add(&mnt->mnt_slave, &old->mnt_slave_list);
|
||||||
|
@ -803,35 +803,36 @@ static void mntput_no_expire(struct mount *mnt)
|
||||||
{
|
{
|
||||||
put_again:
|
put_again:
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
if (likely(atomic_read(&mnt->mnt_longterm))) {
|
if (likely(atomic_read(&mnt->mnt_longterm))) {
|
||||||
mnt_add_count(mnt, -1);
|
mnt_add_count(mnt, -1);
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return;
|
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);
|
mnt_add_count(mnt, -1);
|
||||||
if (mnt_get_count(mnt)) {
|
if (mnt_get_count(mnt)) {
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
mnt_add_count(mnt, -1);
|
mnt_add_count(mnt, -1);
|
||||||
if (likely(mnt_get_count(mnt)))
|
if (likely(mnt_get_count(mnt)))
|
||||||
return;
|
return;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
#endif
|
#endif
|
||||||
if (unlikely(mnt->mnt_pinned)) {
|
if (unlikely(mnt->mnt_pinned)) {
|
||||||
mnt_add_count(mnt, mnt->mnt_pinned + 1);
|
mnt_add_count(mnt, mnt->mnt_pinned + 1);
|
||||||
mnt->mnt_pinned = 0;
|
mnt->mnt_pinned = 0;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
acct_auto_close_mnt(&mnt->mnt);
|
acct_auto_close_mnt(&mnt->mnt);
|
||||||
goto put_again;
|
goto put_again;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&mnt->mnt_instance);
|
list_del(&mnt->mnt_instance);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
mntfree(mnt);
|
mntfree(mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,21 +858,21 @@ EXPORT_SYMBOL(mntget);
|
||||||
|
|
||||||
void mnt_pin(struct vfsmount *mnt)
|
void mnt_pin(struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
real_mount(mnt)->mnt_pinned++;
|
real_mount(mnt)->mnt_pinned++;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mnt_pin);
|
EXPORT_SYMBOL(mnt_pin);
|
||||||
|
|
||||||
void mnt_unpin(struct vfsmount *m)
|
void mnt_unpin(struct vfsmount *m)
|
||||||
{
|
{
|
||||||
struct mount *mnt = real_mount(m);
|
struct mount *mnt = real_mount(m);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
if (mnt->mnt_pinned) {
|
if (mnt->mnt_pinned) {
|
||||||
mnt_add_count(mnt, 1);
|
mnt_add_count(mnt, 1);
|
||||||
mnt->mnt_pinned--;
|
mnt->mnt_pinned--;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mnt_unpin);
|
EXPORT_SYMBOL(mnt_unpin);
|
||||||
|
|
||||||
|
@ -988,12 +989,12 @@ int may_umount_tree(struct vfsmount *m)
|
||||||
BUG_ON(!m);
|
BUG_ON(!m);
|
||||||
|
|
||||||
/* write lock needed for mnt_get_count */
|
/* 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)) {
|
for (p = mnt; p; p = next_mnt(p, mnt)) {
|
||||||
actual_refs += mnt_get_count(p);
|
actual_refs += mnt_get_count(p);
|
||||||
minimum_refs += 2;
|
minimum_refs += 2;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
if (actual_refs > minimum_refs)
|
if (actual_refs > minimum_refs)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1020,10 +1021,10 @@ int may_umount(struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
down_read(&namespace_sem);
|
down_read(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
if (propagate_mount_busy(real_mount(mnt), 2))
|
if (propagate_mount_busy(real_mount(mnt), 2))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_read(&namespace_sem);
|
up_read(&namespace_sem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1040,13 +1041,13 @@ void release_mounts(struct list_head *head)
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct mount *m;
|
struct mount *m;
|
||||||
|
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
dentry = mnt->mnt_mountpoint;
|
dentry = mnt->mnt_mountpoint;
|
||||||
m = mnt->mnt_parent;
|
m = mnt->mnt_parent;
|
||||||
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
|
||||||
mnt->mnt_parent = mnt;
|
mnt->mnt_parent = mnt;
|
||||||
m->mnt_ghosts--;
|
m->mnt_ghosts--;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
mntput(&m->mnt);
|
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_expire);
|
||||||
list_del_init(&p->mnt_list);
|
list_del_init(&p->mnt_list);
|
||||||
__touch_mnt_namespace(p->mnt_ns);
|
__touch_mnt_namespace(p->mnt_ns);
|
||||||
|
if (p->mnt_ns)
|
||||||
|
__mnt_make_shortterm(p);
|
||||||
p->mnt_ns = NULL;
|
p->mnt_ns = NULL;
|
||||||
__mnt_make_shortterm(p);
|
|
||||||
list_del_init(&p->mnt_child);
|
list_del_init(&p->mnt_child);
|
||||||
if (mnt_has_parent(p)) {
|
if (mnt_has_parent(p)) {
|
||||||
p->mnt_parent->mnt_ghosts++;
|
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
|
* probably don't strictly need the lock here if we examined
|
||||||
* all race cases, but it's a slowpath.
|
* all race cases, but it's a slowpath.
|
||||||
*/
|
*/
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
if (mnt_get_count(mnt) != 2) {
|
if (mnt_get_count(mnt) != 2) {
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
if (!xchg(&mnt->mnt_expiry_mark, 1))
|
if (!xchg(&mnt->mnt_expiry_mark, 1))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
@ -1159,7 +1161,7 @@ static int do_umount(struct mount *mnt, int flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
event++;
|
event++;
|
||||||
|
|
||||||
if (!(flags & MNT_DETACH))
|
if (!(flags & MNT_DETACH))
|
||||||
|
@ -1171,7 +1173,7 @@ static int do_umount(struct mount *mnt, int flags)
|
||||||
umount_tree(mnt, 1, &umount_list);
|
umount_tree(mnt, 1, &umount_list);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
return retval;
|
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);
|
q = clone_mnt(p, p->mnt.mnt_root, flag);
|
||||||
if (!q)
|
if (!q)
|
||||||
goto Enomem;
|
goto Enomem;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
list_add_tail(&q->mnt_list, &res->mnt_list);
|
list_add_tail(&q->mnt_list, &res->mnt_list);
|
||||||
attach_mnt(q, &path);
|
attach_mnt(q, &path);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
Enomem:
|
Enomem:
|
||||||
if (res) {
|
if (res) {
|
||||||
LIST_HEAD(umount_list);
|
LIST_HEAD(umount_list);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
umount_tree(res, 0, &umount_list);
|
umount_tree(res, 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1318,9 +1320,9 @@ void drop_collected_mounts(struct vfsmount *mnt)
|
||||||
{
|
{
|
||||||
LIST_HEAD(umount_list);
|
LIST_HEAD(umount_list);
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
umount_tree(real_mount(mnt), 0, &umount_list);
|
umount_tree(real_mount(mnt), 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
}
|
}
|
||||||
|
@ -1448,7 +1450,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
|
||||||
if (err)
|
if (err)
|
||||||
goto out_cleanup_ids;
|
goto out_cleanup_ids;
|
||||||
|
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
|
|
||||||
if (IS_MNT_SHARED(dest_mnt)) {
|
if (IS_MNT_SHARED(dest_mnt)) {
|
||||||
for (p = source_mnt; p; p = next_mnt(p, source_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);
|
list_del_init(&child->mnt_hash);
|
||||||
commit_tree(child);
|
commit_tree(child);
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1565,10 +1567,10 @@ static int do_change_type(struct path *path, int flag)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
|
for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
|
||||||
change_mnt_propagation(m, type);
|
change_mnt_propagation(m, type);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
|
@ -1617,9 +1619,9 @@ static int do_loopback(struct path *path, char *old_name,
|
||||||
|
|
||||||
err = graft_tree(mnt, path);
|
err = graft_tree(mnt, path);
|
||||||
if (err) {
|
if (err) {
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
umount_tree(mnt, 0, &umount_list);
|
umount_tree(mnt, 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
out2:
|
out2:
|
||||||
unlock_mount(path);
|
unlock_mount(path);
|
||||||
|
@ -1677,16 +1679,16 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
|
||||||
else
|
else
|
||||||
err = do_remount_sb(sb, flags, data, 0);
|
err = do_remount_sb(sb, flags, data, 0);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
|
mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
|
||||||
mnt->mnt.mnt_flags = mnt_flags;
|
mnt->mnt.mnt_flags = mnt_flags;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
up_write(&sb->s_umount);
|
up_write(&sb->s_umount);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
touch_mnt_namespace(mnt->mnt_ns);
|
touch_mnt_namespace(mnt->mnt_ns);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1893,9 +1895,9 @@ fail:
|
||||||
/* remove m from any expiration list it may be on */
|
/* remove m from any expiration list it may be on */
|
||||||
if (!list_empty(&mnt->mnt_expire)) {
|
if (!list_empty(&mnt->mnt_expire)) {
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
list_del_init(&mnt->mnt_expire);
|
list_del_init(&mnt->mnt_expire);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
}
|
}
|
||||||
mntput(m);
|
mntput(m);
|
||||||
|
@ -1911,11 +1913,11 @@ fail:
|
||||||
void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
|
void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
|
||||||
{
|
{
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
|
|
||||||
list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
|
list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
|
||||||
|
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mnt_set_expiry);
|
EXPORT_SYMBOL(mnt_set_expiry);
|
||||||
|
@ -1935,7 +1937,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
|
|
||||||
/* extract from the expiration list every vfsmount that matches the
|
/* extract from the expiration list every vfsmount that matches the
|
||||||
* following criteria:
|
* following criteria:
|
||||||
|
@ -1954,7 +1956,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
|
||||||
touch_mnt_namespace(mnt->mnt_ns);
|
touch_mnt_namespace(mnt->mnt_ns);
|
||||||
umount_tree(mnt, 1, &umounts);
|
umount_tree(mnt, 1, &umounts);
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
|
|
||||||
release_mounts(&umounts);
|
release_mounts(&umounts);
|
||||||
|
@ -2218,9 +2220,9 @@ void mnt_make_shortterm(struct vfsmount *m)
|
||||||
struct mount *mnt = real_mount(m);
|
struct mount *mnt = real_mount(m);
|
||||||
if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
|
if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
|
||||||
return;
|
return;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
atomic_dec(&mnt->mnt_longterm);
|
atomic_dec(&mnt->mnt_longterm);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2250,9 +2252,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
new_ns->root = new;
|
new_ns->root = new;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
list_add_tail(&new_ns->list, &new->mnt_list);
|
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
|
* 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 path_is_under(struct path *path1, struct path *path2)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
br_read_lock(vfsmount_lock);
|
br_read_lock(&vfsmount_lock);
|
||||||
res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
|
res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(path_is_under);
|
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 */
|
/* make sure we can reach put_old from new_root */
|
||||||
if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
|
if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
|
||||||
goto out4;
|
goto out4;
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
detach_mnt(new_mnt, &parent_path);
|
detach_mnt(new_mnt, &parent_path);
|
||||||
detach_mnt(root_mnt, &root_parent);
|
detach_mnt(root_mnt, &root_parent);
|
||||||
/* mount old root on put_old */
|
/* mount old root on put_old */
|
||||||
|
@ -2513,7 +2515,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
|
||||||
/* mount new_root on / */
|
/* mount new_root on / */
|
||||||
attach_mnt(new_mnt, &root_parent);
|
attach_mnt(new_mnt, &root_parent);
|
||||||
touch_mnt_namespace(current->nsproxy->mnt_ns);
|
touch_mnt_namespace(current->nsproxy->mnt_ns);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
chroot_fs_refs(&root, &new);
|
chroot_fs_refs(&root, &new);
|
||||||
error = 0;
|
error = 0;
|
||||||
out4:
|
out4:
|
||||||
|
@ -2576,7 +2578,7 @@ void __init mnt_init(void)
|
||||||
for (u = 0; u < HASH_SIZE; u++)
|
for (u = 0; u < HASH_SIZE; u++)
|
||||||
INIT_LIST_HEAD(&mount_hashtable[u]);
|
INIT_LIST_HEAD(&mount_hashtable[u]);
|
||||||
|
|
||||||
br_lock_init(vfsmount_lock);
|
br_lock_init(&vfsmount_lock);
|
||||||
|
|
||||||
err = sysfs_init();
|
err = sysfs_init();
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -2596,9 +2598,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
|
||||||
if (!atomic_dec_and_test(&ns->count))
|
if (!atomic_dec_and_test(&ns->count))
|
||||||
return;
|
return;
|
||||||
down_write(&namespace_sem);
|
down_write(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
umount_tree(ns->root, 0, &umount_list);
|
umount_tree(ns->root, 0, &umount_list);
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
up_write(&namespace_sem);
|
up_write(&namespace_sem);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
kfree(ns);
|
kfree(ns);
|
||||||
|
|
|
@ -221,6 +221,10 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
|
||||||
|
|
||||||
already_written = 0;
|
already_written = 0;
|
||||||
|
|
||||||
|
errno = file_update_time(file);
|
||||||
|
if (errno)
|
||||||
|
goto outrel;
|
||||||
|
|
||||||
bouncebuffer = vmalloc(bufsize);
|
bouncebuffer = vmalloc(bufsize);
|
||||||
if (!bouncebuffer) {
|
if (!bouncebuffer) {
|
||||||
errno = -EIO; /* -ENOMEM */
|
errno = -EIO; /* -ENOMEM */
|
||||||
|
@ -252,8 +256,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
|
||||||
}
|
}
|
||||||
vfree(bouncebuffer);
|
vfree(bouncebuffer);
|
||||||
|
|
||||||
file_update_time(file);
|
|
||||||
|
|
||||||
*ppos = pos;
|
*ppos = pos;
|
||||||
|
|
||||||
if (pos > i_size_read(inode)) {
|
if (pos > i_size_read(inode)) {
|
||||||
|
|
|
@ -23,17 +23,17 @@ struct ncp_mount_data_kernel {
|
||||||
unsigned long flags; /* NCP_MOUNT_* flags */
|
unsigned long flags; /* NCP_MOUNT_* flags */
|
||||||
unsigned int int_flags; /* internal flags */
|
unsigned int int_flags; /* internal flags */
|
||||||
#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001
|
#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? */
|
struct pid *wdog_pid; /* Who cares for our watchdog packets? */
|
||||||
unsigned int ncp_fd; /* The socket to the ncp port */
|
unsigned int ncp_fd; /* The socket to the ncp port */
|
||||||
unsigned int time_out; /* How long should I wait after
|
unsigned int time_out; /* How long should I wait after
|
||||||
sending a NCP request? */
|
sending a NCP request? */
|
||||||
unsigned int retry_count; /* And how often should I retry? */
|
unsigned int retry_count; /* And how often should I retry? */
|
||||||
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
|
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
|
||||||
__kernel_uid32_t uid;
|
uid_t uid;
|
||||||
__kernel_gid32_t gid;
|
gid_t gid;
|
||||||
__kernel_mode_t file_mode;
|
umode_t file_mode;
|
||||||
__kernel_mode_t dir_mode;
|
umode_t dir_mode;
|
||||||
int info_fd;
|
int info_fd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
56
fs/nfs/dir.c
56
fs/nfs/dir.c
|
@ -1354,10 +1354,10 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_NFS_V4
|
#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 = {
|
const struct dentry_operations nfs4_dentry_operations = {
|
||||||
.d_revalidate = nfs_open_revalidate,
|
.d_revalidate = nfs4_lookup_revalidate,
|
||||||
.d_delete = nfs_dentry_delete,
|
.d_delete = nfs_dentry_delete,
|
||||||
.d_iput = nfs_dentry_iput,
|
.d_iput = nfs_dentry_iput,
|
||||||
.d_automount = nfs_d_automount,
|
.d_automount = nfs_d_automount,
|
||||||
|
@ -1519,13 +1519,11 @@ no_open:
|
||||||
return nfs_lookup(dir, dentry, nd);
|
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 dentry *parent = NULL;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
struct inode *dir;
|
struct inode *dir;
|
||||||
struct nfs_open_context *ctx;
|
|
||||||
struct iattr attr;
|
|
||||||
int openflags, ret = 0;
|
int openflags, ret = 0;
|
||||||
|
|
||||||
if (nd->flags & LOOKUP_RCU)
|
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 */
|
/* We cannot do exclusive creation on a positive dentry */
|
||||||
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
||||||
goto no_open_dput;
|
goto no_open_dput;
|
||||||
/* We can't create new files here */
|
|
||||||
openflags &= ~(O_CREAT|O_EXCL);
|
|
||||||
|
|
||||||
ctx = create_nfs_open_context(dentry, openflags);
|
/* Let f_op->open() actually open (and revalidate) the file */
|
||||||
ret = PTR_ERR(ctx);
|
ret = 1;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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:
|
out:
|
||||||
dput(parent);
|
dput(parent);
|
||||||
return ret;
|
return ret;
|
||||||
out_drop:
|
|
||||||
d_drop(dentry);
|
|
||||||
ret = 0;
|
|
||||||
out_put_ctx:
|
|
||||||
put_nfs_open_context(ctx);
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
no_open_dput:
|
no_open_dput:
|
||||||
dput(parent);
|
dput(parent);
|
||||||
|
|
|
@ -879,12 +879,81 @@ const struct file_operations nfs_file_operations = {
|
||||||
static int
|
static int
|
||||||
nfs4_file_open(struct inode *inode, struct file *filp)
|
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
|
* If no cached dentry exists or if it's negative, NFSv4 handled the
|
||||||
* this point, then something is very wrong
|
* 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 = {
|
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);
|
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,
|
static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
|
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
struct nilfs_root *root = NILFS_I(inode)->i_root;
|
struct nilfs_root *root = NILFS_I(inode)->i_root;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE ||
|
if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) {
|
||||||
(connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE))
|
*lenp = NILFS_FID_SIZE_CONNECTABLE;
|
||||||
return 255;
|
return 255;
|
||||||
|
}
|
||||||
|
if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) {
|
||||||
|
*lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
fid->cno = root->cno;
|
fid->cno = root->cno;
|
||||||
fid->ino = inode->i_ino;
|
fid->ino = inode->i_ino;
|
||||||
fid->gen = inode->i_generation;
|
fid->gen = inode->i_generation;
|
||||||
|
|
||||||
if (connectable && !S_ISDIR(inode->i_mode)) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
parent = dentry->d_parent->d_inode;
|
|
||||||
fid->parent_ino = parent->i_ino;
|
fid->parent_ino = parent->i_ino;
|
||||||
fid->parent_gen = parent->i_generation;
|
fid->parent_gen = parent->i_generation;
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
type = FILEID_NILFS_WITH_PARENT;
|
type = FILEID_NILFS_WITH_PARENT;
|
||||||
*lenp = NILFS_FID_SIZE_CONNECTABLE;
|
*lenp = NILFS_FID_SIZE_CONNECTABLE;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -123,7 +123,7 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__fsnotify_parent);
|
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 *inode_mark,
|
||||||
struct fsnotify_mark *vfsmount_mark,
|
struct fsnotify_mark *vfsmount_mark,
|
||||||
__u32 mask, void *data,
|
__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;
|
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"
|
" inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
|
||||||
" data=%p data_is=%d cookie=%d event=%p\n",
|
" 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,
|
inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
|
||||||
data_is, cookie, *event);
|
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) {
|
if (inode_group > vfsmount_group) {
|
||||||
/* handle inode */
|
/* 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);
|
data_is, cookie, file_name, &event);
|
||||||
/* we didn't use the vfsmount_mark */
|
/* we didn't use the vfsmount_mark */
|
||||||
vfsmount_group = NULL;
|
vfsmount_group = NULL;
|
||||||
} else if (vfsmount_group > inode_group) {
|
} 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);
|
data_is, cookie, file_name, &event);
|
||||||
inode_group = NULL;
|
inode_group = NULL;
|
||||||
} else {
|
} 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,
|
mask, data, data_is, cookie, file_name,
|
||||||
&event);
|
&event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2096,7 +2096,9 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
|
||||||
err = file_remove_suid(file);
|
err = file_remove_suid(file);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
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,
|
written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
|
||||||
count);
|
count);
|
||||||
out:
|
out:
|
||||||
|
|
|
@ -422,45 +422,46 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
|
||||||
struct ocfs2_blockcheck_stats *stats)
|
struct ocfs2_blockcheck_stats *stats)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct ocfs2_block_check check;
|
u32 bc_crc32e;
|
||||||
|
u16 bc_ecc;
|
||||||
u32 crc, ecc;
|
u32 crc, ecc;
|
||||||
|
|
||||||
ocfs2_blockcheck_inc_check(stats);
|
ocfs2_blockcheck_inc_check(stats);
|
||||||
|
|
||||||
check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
|
bc_crc32e = le32_to_cpu(bc->bc_crc32e);
|
||||||
check.bc_ecc = le16_to_cpu(bc->bc_ecc);
|
bc_ecc = le16_to_cpu(bc->bc_ecc);
|
||||||
|
|
||||||
memset(bc, 0, sizeof(struct ocfs2_block_check));
|
memset(bc, 0, sizeof(struct ocfs2_block_check));
|
||||||
|
|
||||||
/* Fast path - if the crc32 validates, we're good to go */
|
/* Fast path - if the crc32 validates, we're good to go */
|
||||||
crc = crc32_le(~0, data, blocksize);
|
crc = crc32_le(~0, data, blocksize);
|
||||||
if (crc == check.bc_crc32e)
|
if (crc == bc_crc32e)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ocfs2_blockcheck_inc_failure(stats);
|
ocfs2_blockcheck_inc_failure(stats);
|
||||||
mlog(ML_ERROR,
|
mlog(ML_ERROR,
|
||||||
"CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
|
"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 */
|
/* Ok, try ECC fixups */
|
||||||
ecc = ocfs2_hamming_encode_block(data, blocksize);
|
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 */
|
/* And check the crc32 again */
|
||||||
crc = crc32_le(~0, data, blocksize);
|
crc = crc32_le(~0, data, blocksize);
|
||||||
if (crc == check.bc_crc32e) {
|
if (crc == bc_crc32e) {
|
||||||
ocfs2_blockcheck_inc_recover(stats);
|
ocfs2_blockcheck_inc_recover(stats);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
|
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;
|
rc = -EIO;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
|
bc->bc_crc32e = cpu_to_le32(bc_crc32e);
|
||||||
bc->bc_ecc = cpu_to_le16(check.bc_ecc);
|
bc->bc_ecc = cpu_to_le16(bc_ecc);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +529,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
|
||||||
struct ocfs2_blockcheck_stats *stats)
|
struct ocfs2_blockcheck_stats *stats)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
struct ocfs2_block_check check;
|
u32 bc_crc32e;
|
||||||
|
u16 bc_ecc;
|
||||||
u32 crc, ecc, fix;
|
u32 crc, ecc, fix;
|
||||||
|
|
||||||
BUG_ON(nr < 0);
|
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);
|
ocfs2_blockcheck_inc_check(stats);
|
||||||
|
|
||||||
check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
|
bc_crc32e = le32_to_cpu(bc->bc_crc32e);
|
||||||
check.bc_ecc = le16_to_cpu(bc->bc_ecc);
|
bc_ecc = le16_to_cpu(bc->bc_ecc);
|
||||||
|
|
||||||
memset(bc, 0, sizeof(struct ocfs2_block_check));
|
memset(bc, 0, sizeof(struct ocfs2_block_check));
|
||||||
|
|
||||||
/* Fast path - if the crc32 validates, we're good to go */
|
/* Fast path - if the crc32 validates, we're good to go */
|
||||||
for (i = 0, crc = ~0; i < nr; i++)
|
for (i = 0, crc = ~0; i < nr; i++)
|
||||||
crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
|
crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
|
||||||
if (crc == check.bc_crc32e)
|
if (crc == bc_crc32e)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ocfs2_blockcheck_inc_failure(stats);
|
ocfs2_blockcheck_inc_failure(stats);
|
||||||
mlog(ML_ERROR,
|
mlog(ML_ERROR,
|
||||||
"CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
|
"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 */
|
/* Ok, try ECC fixups */
|
||||||
for (i = 0, ecc = 0; i < nr; i++) {
|
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,
|
||||||
bhs[i]->b_size * 8 * i);
|
bhs[i]->b_size * 8 * i);
|
||||||
}
|
}
|
||||||
fix = ecc ^ check.bc_ecc;
|
fix = ecc ^ bc_ecc;
|
||||||
for (i = 0; i < nr; i++) {
|
for (i = 0; i < nr; i++) {
|
||||||
/*
|
/*
|
||||||
* Try the fix against each buffer. It will only affect
|
* 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 */
|
/* And check the crc32 again */
|
||||||
for (i = 0, crc = ~0; i < nr; i++)
|
for (i = 0, crc = ~0; i < nr; i++)
|
||||||
crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
|
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);
|
ocfs2_blockcheck_inc_recover(stats);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
|
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;
|
rc = -EIO;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
|
bc->bc_crc32e = cpu_to_le32(bc_crc32e);
|
||||||
bc->bc_ecc = cpu_to_le16(check.bc_ecc);
|
bc->bc_ecc = cpu_to_le16(bc_ecc);
|
||||||
|
|
||||||
return rc;
|
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;
|
struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf;
|
||||||
char *name;
|
char *name;
|
||||||
struct list_head *iter, *head=NULL;
|
struct list_head *iter, *head=NULL;
|
||||||
u64 cookie;
|
__be64 cookie;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
u8 node;
|
u8 node;
|
||||||
|
|
||||||
|
|
|
@ -679,7 +679,7 @@ struct dlm_query_join_packet {
|
||||||
};
|
};
|
||||||
|
|
||||||
union dlm_query_join_response {
|
union dlm_query_join_response {
|
||||||
u32 intval;
|
__be32 intval;
|
||||||
struct dlm_query_join_packet packet;
|
struct dlm_query_join_packet packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -755,8 +755,8 @@ struct dlm_query_region {
|
||||||
struct dlm_node_info {
|
struct dlm_node_info {
|
||||||
u8 ni_nodenum;
|
u8 ni_nodenum;
|
||||||
u8 pad1;
|
u8 pad1;
|
||||||
u16 ni_ipv4_port;
|
__be16 ni_ipv4_port;
|
||||||
u32 ni_ipv4_address;
|
__be32 ni_ipv4_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dlm_query_nodeinfo {
|
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;
|
union dlm_query_join_response response;
|
||||||
|
|
||||||
response.packet = *packet;
|
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,
|
static void dlm_query_join_wire_to_packet(u32 wire,
|
||||||
|
|
|
@ -177,21 +177,23 @@ bail:
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
|
static int ocfs2_encode_fh(struct inode *inode, u32 *fh_in, int *max_len,
|
||||||
int connectable)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
int len = *max_len;
|
int len = *max_len;
|
||||||
int type = 1;
|
int type = 1;
|
||||||
u64 blkno;
|
u64 blkno;
|
||||||
u32 generation;
|
u32 generation;
|
||||||
__le32 *fh = (__force __le32 *) fh_in;
|
__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,
|
trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len,
|
||||||
dentry->d_name.name,
|
dentry->d_name.name,
|
||||||
fh, len, connectable);
|
fh, len, connectable);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (connectable && (len < 6)) {
|
if (parent && (len < 6)) {
|
||||||
*max_len = 6;
|
*max_len = 6;
|
||||||
type = 255;
|
type = 255;
|
||||||
goto bail;
|
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[1] = cpu_to_le32((u32)(blkno & 0xffffffff));
|
||||||
fh[2] = cpu_to_le32(generation);
|
fh[2] = cpu_to_le32(generation);
|
||||||
|
|
||||||
if (connectable && !S_ISDIR(inode->i_mode)) {
|
if (parent) {
|
||||||
struct inode *parent;
|
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
|
||||||
|
|
||||||
parent = dentry->d_parent->d_inode;
|
|
||||||
blkno = OCFS2_I(parent)->ip_blkno;
|
blkno = OCFS2_I(parent)->ip_blkno;
|
||||||
generation = parent->i_generation;
|
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[4] = cpu_to_le32((u32)(blkno & 0xffffffff));
|
||||||
fh[5] = cpu_to_le32(generation);
|
fh[5] = cpu_to_le32(generation);
|
||||||
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
len = 6;
|
len = 6;
|
||||||
type = 2;
|
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);
|
inode->i_gid = le32_to_cpu(fe->i_gid);
|
||||||
|
|
||||||
/* Fast symlinks will have i_size but no allocated clusters. */
|
/* 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;
|
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_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_sec = le64_to_cpu(fe->i_atime);
|
||||||
inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
|
inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
|
||||||
inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
|
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;
|
OCFS2_I(inode)->ip_dir_lock_gen = 1;
|
||||||
break;
|
break;
|
||||||
case S_IFLNK:
|
case S_IFLNK:
|
||||||
if (ocfs2_inode_is_fast_symlink(inode))
|
inode->i_op = &ocfs2_symlink_inode_operations;
|
||||||
inode->i_op = &ocfs2_fast_symlink_inode_operations;
|
|
||||||
else
|
|
||||||
inode->i_op = &ocfs2_symlink_inode_operations;
|
|
||||||
i_size_write(inode, le64_to_cpu(fe->i_size));
|
i_size_write(inode, le64_to_cpu(fe->i_size));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -864,7 +864,7 @@ int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
|
||||||
if (status)
|
if (status)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
reqp = (struct ocfs2_info_request *)(unsigned long)req_addr;
|
reqp = (struct ocfs2_info_request __user *)(unsigned long)req_addr;
|
||||||
if (!reqp) {
|
if (!reqp) {
|
||||||
status = -EINVAL;
|
status = -EINVAL;
|
||||||
goto bail;
|
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_space_resv sr;
|
||||||
struct ocfs2_new_group_input input;
|
struct ocfs2_new_group_input input;
|
||||||
struct reflink_arguments args;
|
struct reflink_arguments args;
|
||||||
const char *old_path, *new_path;
|
const char __user *old_path;
|
||||||
|
const char __user *new_path;
|
||||||
bool preserve;
|
bool preserve;
|
||||||
struct ocfs2_info info;
|
struct ocfs2_info info;
|
||||||
|
void __user *argp = (void __user *)arg;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case OCFS2_IOC_GETFLAGS:
|
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);
|
return ocfs2_group_add(inode, &input);
|
||||||
case OCFS2_IOC_REFLINK:
|
case OCFS2_IOC_REFLINK:
|
||||||
if (copy_from_user(&args, (struct reflink_arguments *)arg,
|
if (copy_from_user(&args, argp, sizeof(args)))
|
||||||
sizeof(args)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
old_path = (const char *)(unsigned long)args.old_path;
|
old_path = (const char __user *)(unsigned long)args.old_path;
|
||||||
new_path = (const char *)(unsigned long)args.new_path;
|
new_path = (const char __user *)(unsigned long)args.new_path;
|
||||||
preserve = (args.preserve != 0);
|
preserve = (args.preserve != 0);
|
||||||
|
|
||||||
return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
|
return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
|
||||||
case OCFS2_IOC_INFO:
|
case OCFS2_IOC_INFO:
|
||||||
if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
|
if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
|
||||||
sizeof(struct ocfs2_info)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return ocfs2_info_handle(inode, &info, 0);
|
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))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (copy_from_user(&range, (struct fstrim_range *)arg,
|
if (copy_from_user(&range, argp, sizeof(range)))
|
||||||
sizeof(range)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
ret = ocfs2_trim_fs(sb, &range);
|
ret = ocfs2_trim_fs(sb, &range);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (copy_to_user((struct fstrim_range *)arg, &range,
|
if (copy_to_user(argp, &range, sizeof(range)))
|
||||||
sizeof(range)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case OCFS2_IOC_MOVE_EXT:
|
case OCFS2_IOC_MOVE_EXT:
|
||||||
return ocfs2_ioctl_move_extents(filp, (void __user *)arg);
|
return ocfs2_ioctl_move_extents(filp, argp);
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
}
|
}
|
||||||
|
@ -988,6 +986,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
||||||
struct reflink_arguments args;
|
struct reflink_arguments args;
|
||||||
struct inode *inode = file->f_path.dentry->d_inode;
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
struct ocfs2_info info;
|
struct ocfs2_info info;
|
||||||
|
void __user *argp = (void __user *)arg;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case OCFS2_IOC32_GETFLAGS:
|
case OCFS2_IOC32_GETFLAGS:
|
||||||
|
@ -1006,16 +1005,14 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
|
||||||
case FITRIM:
|
case FITRIM:
|
||||||
break;
|
break;
|
||||||
case OCFS2_IOC_REFLINK:
|
case OCFS2_IOC_REFLINK:
|
||||||
if (copy_from_user(&args, (struct reflink_arguments *)arg,
|
if (copy_from_user(&args, argp, sizeof(args)))
|
||||||
sizeof(args)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
preserve = (args.preserve != 0);
|
preserve = (args.preserve != 0);
|
||||||
|
|
||||||
return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
|
return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
|
||||||
compat_ptr(args.new_path), preserve);
|
compat_ptr(args.new_path), preserve);
|
||||||
case OCFS2_IOC_INFO:
|
case OCFS2_IOC_INFO:
|
||||||
if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
|
if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
|
||||||
sizeof(struct ocfs2_info)))
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
return ocfs2_info_handle(inode, &info, 1);
|
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;
|
context->file = filp;
|
||||||
|
|
||||||
if (argp) {
|
if (argp) {
|
||||||
if (copy_from_user(&range, (struct ocfs2_move_extents *)argp,
|
if (copy_from_user(&range, argp, sizeof(range))) {
|
||||||
sizeof(range))) {
|
|
||||||
status = -EFAULT;
|
status = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -1138,8 +1137,7 @@ out:
|
||||||
* length and new_offset even if failure happens somewhere.
|
* length and new_offset even if failure happens somewhere.
|
||||||
*/
|
*/
|
||||||
if (argp) {
|
if (argp) {
|
||||||
if (copy_to_user((struct ocfs2_move_extents *)argp, &range,
|
if (copy_to_user(argp, &range, sizeof(range)))
|
||||||
sizeof(range)))
|
|
||||||
status = -EFAULT;
|
status = -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir,
|
||||||
fe = (struct ocfs2_dinode *) new_fe_bh->b_data;
|
fe = (struct ocfs2_dinode *) new_fe_bh->b_data;
|
||||||
inode->i_rdev = 0;
|
inode->i_rdev = 0;
|
||||||
newsize = l - 1;
|
newsize = l - 1;
|
||||||
|
inode->i_op = &ocfs2_symlink_inode_operations;
|
||||||
if (l > ocfs2_fast_symlink_chars(sb)) {
|
if (l > ocfs2_fast_symlink_chars(sb)) {
|
||||||
u32 offset = 0;
|
u32 offset = 0;
|
||||||
|
|
||||||
inode->i_op = &ocfs2_symlink_inode_operations;
|
|
||||||
status = dquot_alloc_space_nodirty(inode,
|
status = dquot_alloc_space_nodirty(inode,
|
||||||
ocfs2_clusters_to_bytes(osb->sb, 1));
|
ocfs2_clusters_to_bytes(osb->sb, 1));
|
||||||
if (status)
|
if (status)
|
||||||
goto bail;
|
goto bail;
|
||||||
did_quota = 1;
|
did_quota = 1;
|
||||||
|
inode->i_mapping->a_ops = &ocfs2_aops;
|
||||||
status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
|
status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
|
||||||
new_fe_bh,
|
new_fe_bh,
|
||||||
handle, data_ac, NULL,
|
handle, data_ac, NULL,
|
||||||
|
@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir,
|
||||||
i_size_write(inode, newsize);
|
i_size_write(inode, newsize);
|
||||||
inode->i_blocks = ocfs2_inode_sector_count(inode);
|
inode->i_blocks = ocfs2_inode_sector_count(inode);
|
||||||
} else {
|
} 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);
|
memcpy((char *) fe->id2.i_symlink, symname, l);
|
||||||
i_size_write(inode, newsize);
|
i_size_write(inode, newsize);
|
||||||
inode->i_blocks = 0;
|
inode->i_blocks = 0;
|
||||||
|
|
|
@ -54,101 +54,40 @@
|
||||||
#include "buffer_head_io.h"
|
#include "buffer_head_io.h"
|
||||||
|
|
||||||
|
|
||||||
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
|
static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page)
|
||||||
struct buffer_head **bh)
|
|
||||||
{
|
{
|
||||||
int status;
|
struct inode *inode = page->mapping->host;
|
||||||
char *link = NULL;
|
struct buffer_head *bh;
|
||||||
|
int status = ocfs2_read_inode_block(inode, &bh);
|
||||||
struct ocfs2_dinode *fe;
|
struct ocfs2_dinode *fe;
|
||||||
|
const char *link;
|
||||||
|
void *kaddr;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
status = ocfs2_read_inode_block(inode, bh);
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
mlog_errno(status);
|
mlog_errno(status);
|
||||||
link = ERR_PTR(status);
|
return status;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fe = (struct ocfs2_dinode *) (*bh)->b_data;
|
fe = (struct ocfs2_dinode *) bh->b_data;
|
||||||
link = (char *) fe->id2.i_symlink;
|
link = (char *) fe->id2.i_symlink;
|
||||||
bail:
|
/* will be less than a page size */
|
||||||
|
len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb));
|
||||||
return link;
|
kaddr = kmap_atomic(page);
|
||||||
}
|
memcpy(kaddr, link, len + 1);
|
||||||
|
kunmap_atomic(kaddr);
|
||||||
static int ocfs2_readlink(struct dentry *dentry,
|
SetPageUptodate(page);
|
||||||
char __user *buffer,
|
unlock_page(page);
|
||||||
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);
|
|
||||||
|
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
out:
|
return 0;
|
||||||
if (ret < 0)
|
|
||||||
mlog_errno(ret);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ocfs2_fast_follow_link(struct dentry *dentry,
|
const struct address_space_operations ocfs2_fast_symlink_aops = {
|
||||||
struct nameidata *nd)
|
.readpage = ocfs2_fast_symlink_readpage,
|
||||||
{
|
};
|
||||||
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 inode_operations ocfs2_symlink_inode_operations = {
|
const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||||
.readlink = page_readlink,
|
.readlink = generic_readlink,
|
||||||
.follow_link = page_follow_link_light,
|
.follow_link = page_follow_link_light,
|
||||||
.put_link = page_put_link,
|
.put_link = page_put_link,
|
||||||
.getattr = ocfs2_getattr,
|
.getattr = ocfs2_getattr,
|
||||||
|
@ -159,15 +98,3 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
|
||||||
.removexattr = generic_removexattr,
|
.removexattr = generic_removexattr,
|
||||||
.fiemap = ocfs2_fiemap,
|
.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
|
#define OCFS2_SYMLINK_H
|
||||||
|
|
||||||
extern const struct inode_operations ocfs2_symlink_inode_operations;
|
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.
|
* 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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
|
int open_check_o_direct(struct file *f)
|
||||||
struct file *f,
|
{
|
||||||
int (*open)(struct inode *, struct file *),
|
/* NB: we're sure to have correct a_ops only after f_op->open */
|
||||||
const struct cred *cred)
|
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 = {};
|
static const struct file_operations empty_fops = {};
|
||||||
struct inode *inode;
|
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);
|
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;
|
return f;
|
||||||
|
|
||||||
cleanup_all:
|
cleanup_all:
|
||||||
|
@ -744,12 +747,29 @@ cleanup_all:
|
||||||
f->f_path.dentry = NULL;
|
f->f_path.dentry = NULL;
|
||||||
f->f_path.mnt = NULL;
|
f->f_path.mnt = NULL;
|
||||||
cleanup_file:
|
cleanup_file:
|
||||||
put_filp(f);
|
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
mntput(mnt);
|
mntput(mnt);
|
||||||
return ERR_PTR(error);
|
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
|
* lookup_instantiate_filp - instantiates the open intent filp
|
||||||
* @nd: pointer to nameidata
|
* @nd: pointer to nameidata
|
||||||
|
@ -804,13 +824,31 @@ struct file *nameidata_to_filp(struct nameidata *nd)
|
||||||
|
|
||||||
/* Pick up the filp from the open intent */
|
/* Pick up the filp from the open intent */
|
||||||
filp = nd->intent.open.file;
|
filp = nd->intent.open.file;
|
||||||
nd->intent.open.file = NULL;
|
|
||||||
|
|
||||||
/* Has the filesystem initialised the file for us? */
|
/* 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);
|
path_get(&nd->path);
|
||||||
filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
|
res = do_dentry_open(nd->path.dentry, nd->path.mnt,
|
||||||
NULL, cred);
|
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;
|
return filp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,8 +654,11 @@ out:
|
||||||
wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
|
wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
|
||||||
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
|
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
|
||||||
}
|
}
|
||||||
if (ret > 0)
|
if (ret > 0) {
|
||||||
file_update_time(filp);
|
int err = file_update_time(filp);
|
||||||
|
if (err)
|
||||||
|
ret = err;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -257,12 +257,12 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
|
||||||
prev_src_mnt = child;
|
prev_src_mnt = child;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(&vfsmount_lock);
|
||||||
while (!list_empty(&tmp_list)) {
|
while (!list_empty(&tmp_list)) {
|
||||||
child = list_first_entry(&tmp_list, struct mount, mnt_hash);
|
child = list_first_entry(&tmp_list, struct mount, mnt_hash);
|
||||||
umount_tree(child, 0, &umount_list);
|
umount_tree(child, 0, &umount_list);
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(&vfsmount_lock);
|
||||||
release_mounts(&umount_list);
|
release_mounts(&umount_list);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,12 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
|
||||||
|
|
||||||
poll_wait(file, &p->ns->poll, 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) {
|
if (p->m.poll_event != ns->event) {
|
||||||
p->m.poll_event = ns->event;
|
p->m.poll_event = ns->event;
|
||||||
res |= POLLERR | POLLPRI;
|
res |= POLLERR | POLLPRI;
|
||||||
}
|
}
|
||||||
br_read_unlock(vfsmount_lock);
|
br_read_unlock(&vfsmount_lock);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
33
fs/readdir.c
33
fs/readdir.c
|
@ -108,11 +108,11 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
||||||
int error;
|
int error;
|
||||||
struct file * file;
|
struct file * file;
|
||||||
struct readdir_callback buf;
|
struct readdir_callback buf;
|
||||||
|
int fput_needed;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.result = 0;
|
buf.result = 0;
|
||||||
buf.dirent = dirent;
|
buf.dirent = dirent;
|
||||||
|
@ -121,8 +121,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
|
||||||
if (buf.result)
|
if (buf.result)
|
||||||
error = buf.result;
|
error = buf.result;
|
||||||
|
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,16 +194,15 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
||||||
struct file * file;
|
struct file * file;
|
||||||
struct linux_dirent __user * lastdirent;
|
struct linux_dirent __user * lastdirent;
|
||||||
struct getdents_callback buf;
|
struct getdents_callback buf;
|
||||||
|
int fput_needed;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EFAULT;
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.current_dir = dirent;
|
buf.current_dir = dirent;
|
||||||
buf.previous = NULL;
|
buf.previous = NULL;
|
||||||
|
@ -221,8 +219,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
|
||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,16 +275,15 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
||||||
struct file * file;
|
struct file * file;
|
||||||
struct linux_dirent64 __user * lastdirent;
|
struct linux_dirent64 __user * lastdirent;
|
||||||
struct getdents_callback64 buf;
|
struct getdents_callback64 buf;
|
||||||
|
int fput_needed;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = -EFAULT;
|
|
||||||
if (!access_ok(VERIFY_WRITE, dirent, count))
|
if (!access_ok(VERIFY_WRITE, dirent, count))
|
||||||
goto out;
|
return -EFAULT;
|
||||||
|
|
||||||
error = -EBADF;
|
file = fget_light(fd, &fput_needed);
|
||||||
file = fget(fd);
|
|
||||||
if (!file)
|
if (!file)
|
||||||
goto out;
|
return -EBADF;
|
||||||
|
|
||||||
buf.current_dir = dirent;
|
buf.current_dir = dirent;
|
||||||
buf.previous = NULL;
|
buf.previous = NULL;
|
||||||
|
@ -305,7 +301,6 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
|
||||||
else
|
else
|
||||||
error = count - buf.count;
|
error = count - buf.count;
|
||||||
}
|
}
|
||||||
fput(file);
|
fput_light(file, fput_needed);
|
||||||
out:
|
|
||||||
return error;
|
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);
|
(fh_type == 6) ? fid->raw[5] : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
|
int reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp,
|
||||||
int need_parent)
|
struct inode *parent)
|
||||||
{
|
{
|
||||||
struct inode *inode = dentry->d_inode;
|
|
||||||
int maxlen = *lenp;
|
int maxlen = *lenp;
|
||||||
|
|
||||||
if (need_parent && (maxlen < 5)) {
|
if (parent && (maxlen < 5)) {
|
||||||
*lenp = 5;
|
*lenp = 5;
|
||||||
return 255;
|
return 255;
|
||||||
} else if (maxlen < 3) {
|
} 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[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
|
||||||
data[2] = inode->i_generation;
|
data[2] = inode->i_generation;
|
||||||
*lenp = 3;
|
*lenp = 3;
|
||||||
/* no room for directory info? return what we've stored so far */
|
if (parent) {
|
||||||
if (maxlen < 5 || !need_parent)
|
data[3] = parent->i_ino;
|
||||||
return 3;
|
data[4] = le32_to_cpu(INODE_PKEY(parent)->k_dir_id);
|
||||||
|
*lenp = 5;
|
||||||
spin_lock(&dentry->d_lock);
|
if (maxlen >= 6) {
|
||||||
inode = dentry->d_parent->d_inode;
|
data[5] = parent->i_generation;
|
||||||
data[3] = inode->i_ino;
|
*lenp = 6;
|
||||||
data[4] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
|
}
|
||||||
*lenp = 5;
|
|
||||||
if (maxlen >= 6) {
|
|
||||||
data[5] = inode->i_generation;
|
|
||||||
*lenp = 6;
|
|
||||||
}
|
}
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
return *lenp;
|
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
|
* the workqueue job (flush_async_commit) needs this lock
|
||||||
*/
|
*/
|
||||||
reiserfs_write_unlock(sb);
|
reiserfs_write_unlock(sb);
|
||||||
|
|
||||||
|
cancel_delayed_work_sync(&REISERFS_SB(sb)->old_work);
|
||||||
flush_workqueue(commit_wq);
|
flush_workqueue(commit_wq);
|
||||||
|
|
||||||
if (!reiserfs_mounted_fs_count) {
|
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);
|
th->t_trans_id, journal->j_trans_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
sb->s_dirt = 1;
|
|
||||||
|
|
||||||
prepared = test_clear_buffer_journal_prepared(bh);
|
prepared = test_clear_buffer_journal_prepared(bh);
|
||||||
clear_buffer_journal_restore_dirty(bh);
|
clear_buffer_journal_restore_dirty(bh);
|
||||||
/* already in this transaction, we are done */
|
/* 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_first = cn;
|
||||||
journal->j_last = cn;
|
journal->j_last = cn;
|
||||||
}
|
}
|
||||||
|
reiserfs_schedule_old_flush(sb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3492,7 +3493,7 @@ static void flush_async_commits(struct work_struct *work)
|
||||||
** flushes any old transactions to disk
|
** flushes any old transactions to disk
|
||||||
** ends the current transaction if it is too old
|
** 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;
|
time_t now;
|
||||||
struct reiserfs_transaction_handle th;
|
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
|
/* safety check so we don't flush while we are replaying the log during
|
||||||
* mount
|
* mount
|
||||||
*/
|
*/
|
||||||
if (list_empty(&journal->j_journal_list)) {
|
if (list_empty(&journal->j_journal_list))
|
||||||
return 0;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* check the current transaction. If there are no writers, and it is
|
/* check the current transaction. If there are no writers, and it is
|
||||||
* too old, finish it, and force the commit blocks to disk
|
* 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);
|
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
|
** it tells us if we should continue with the journal_end, or just return
|
||||||
*/
|
*/
|
||||||
if (!check_journal_end(th, sb, nblocks, flags)) {
|
if (!check_journal_end(th, sb, nblocks, flags)) {
|
||||||
sb->s_dirt = 1;
|
reiserfs_schedule_old_flush(sb);
|
||||||
wake_queued_writers(sb);
|
wake_queued_writers(sb);
|
||||||
reiserfs_async_progress_wait(sb);
|
reiserfs_async_progress_wait(sb);
|
||||||
goto out;
|
goto out;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue