Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6: (21 commits) ext3: PTR_ERR return of wrong pointer in setup_new_group_blocks() ext3: Fix data / filesystem corruption when write fails to copy data ext4: Support for 64-bit quota format ext3: Support for vfsv1 quota format quota: Implement quota format with 64-bit space and inode limits quota: Move definition of QFMT_OCFS2 to linux/quota.h ext2: fix comment in ext2_find_entry about return values ext3: Unify log messages in ext3 ext2: clear uptodate flag on super block I/O error ext2: Unify log messages in ext2 ext3: make "norecovery" an alias for "noload" ext3: Don't update the superblock in ext3_statfs() ext3: journal all modifications in ext3_xattr_set_handle ext2: Explicitly assign values to on-disk enum of filetypes quota: Fix WARN_ON in lookup_one_len const: struct quota_format_ops ubifs: remove manual O_SYNC handling afs: remove manual O_SYNC handling kill wait_on_page_writeback_range vfs: Implement proper O_SYNC semantics ...
This commit is contained in:
commit
3126c136bc
|
@ -32,8 +32,8 @@ journal_dev=devnum When the external journal device's major/minor numbers
|
|||
identified through its new major/minor numbers encoded
|
||||
in devnum.
|
||||
|
||||
noload Don't load the journal on mounting. Note that this forces
|
||||
mount of inconsistent filesystem, which can lead to
|
||||
norecovery Don't load the journal on mounting. Note that this forces
|
||||
noload mount of inconsistent filesystem, which can lead to
|
||||
various problems.
|
||||
|
||||
data=journal All data are committed into the journal prior to being
|
||||
|
|
|
@ -472,7 +472,7 @@ __sync_single_inode) to check if ->writepages has been successful in
|
|||
writing out the whole address_space.
|
||||
|
||||
The Writeback tag is used by filemap*wait* and sync_page* functions,
|
||||
via wait_on_page_writeback_range, to wait for all writeback to
|
||||
via filemap_fdatawait_range, to wait for all writeback to
|
||||
complete. While waiting ->sync_page (if defined) will be called on
|
||||
each page that is found to require writeback.
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _ALPHA_FCNTL_H
|
||||
#define _ALPHA_FCNTL_H
|
||||
|
||||
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
|
||||
located on an ext2 file system */
|
||||
#define O_CREAT 01000 /* not fcntl */
|
||||
#define O_TRUNC 02000 /* not fcntl */
|
||||
#define O_EXCL 04000 /* not fcntl */
|
||||
|
@ -10,13 +8,28 @@
|
|||
|
||||
#define O_NONBLOCK 00004
|
||||
#define O_APPEND 00010
|
||||
#define O_SYNC 040000
|
||||
#define O_DSYNC 040000 /* used to be O_SYNC, see below */
|
||||
#define O_DIRECTORY 0100000 /* must be a directory */
|
||||
#define O_NOFOLLOW 0200000 /* don't follow links */
|
||||
#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */
|
||||
#define O_DIRECT 02000000 /* direct disk access - should check with OSF/1 */
|
||||
#define O_NOATIME 04000000
|
||||
#define O_CLOEXEC 010000000 /* set close_on_exec */
|
||||
/*
|
||||
* Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
|
||||
* the O_SYNC flag. We continue to use the existing numerical value
|
||||
* for O_DSYNC semantics now, but using the correct symbolic name for it.
|
||||
* This new value is used to request true Posix O_SYNC semantics. It is
|
||||
* defined in this strange way to make sure applications compiled against
|
||||
* new headers get at least O_DSYNC semantics on older kernels.
|
||||
*
|
||||
* This has the nice side-effect that we can simply test for O_DSYNC
|
||||
* wherever we do not care if O_DSYNC or O_SYNC is used.
|
||||
*
|
||||
* Note: __O_SYNC must never be used directly.
|
||||
*/
|
||||
#define __O_SYNC 020000000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
|
||||
#define F_GETLK 7
|
||||
#define F_SETLK 8
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
#ifndef _BFIN_FCNTL_H
|
||||
#define _BFIN_FCNTL_H
|
||||
|
||||
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
|
||||
located on an ext2 file system */
|
||||
#define O_DIRECTORY 040000 /* must be a directory */
|
||||
#define O_NOFOLLOW 0100000 /* don't follow links */
|
||||
#define O_DIRECT 0200000 /* direct disk access hint - currently ignored */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
#define O_APPEND 0x0008
|
||||
#define O_SYNC 0x0010
|
||||
#define O_DSYNC 0x0010 /* used to be O_SYNC, see below */
|
||||
#define O_NONBLOCK 0x0080
|
||||
#define O_CREAT 0x0100 /* not fcntl */
|
||||
#define O_TRUNC 0x0200 /* not fcntl */
|
||||
|
@ -18,6 +18,21 @@
|
|||
#define O_NOCTTY 0x0800 /* not fcntl */
|
||||
#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
|
||||
#define O_LARGEFILE 0x2000 /* allow large file opens */
|
||||
/*
|
||||
* Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
|
||||
* the O_SYNC flag. We continue to use the existing numerical value
|
||||
* for O_DSYNC semantics now, but using the correct symbolic name for it.
|
||||
* This new value is used to request true Posix O_SYNC semantics. It is
|
||||
* defined in this strange way to make sure applications compiled against
|
||||
* new headers get at least O_DSYNC semantics on older kernels.
|
||||
*
|
||||
* This has the nice side-effect that we can simply test for O_DSYNC
|
||||
* wherever we do not care if O_DSYNC or O_SYNC is used.
|
||||
*
|
||||
* Note: __O_SYNC must never be used directly.
|
||||
*/
|
||||
#define __O_SYNC 0x4000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
#define O_DIRECT 0x8000 /* direct disk access hint */
|
||||
|
||||
#define F_GETLK 14
|
||||
|
|
|
@ -82,6 +82,7 @@ static int sp_stopping;
|
|||
#define MTSP_O_SHLOCK 0x0010
|
||||
#define MTSP_O_EXLOCK 0x0020
|
||||
#define MTSP_O_ASYNC 0x0040
|
||||
/* XXX: check which of these is actually O_SYNC vs O_DSYNC */
|
||||
#define MTSP_O_FSYNC O_SYNC
|
||||
#define MTSP_O_NOFOLLOW 0x0100
|
||||
#define MTSP_O_SYNC 0x0080
|
||||
|
|
|
@ -26,7 +26,7 @@ void __init prom_init_memory(void)
|
|||
/* override of arch/mips/mm/cache.c: __uncached_access */
|
||||
int __uncached_access(struct file *file, unsigned long addr)
|
||||
{
|
||||
if (file->f_flags & O_SYNC)
|
||||
if (file->f_flags & O_DSYNC)
|
||||
return 1;
|
||||
|
||||
return addr >= __pa(high_memory) ||
|
||||
|
|
|
@ -194,7 +194,7 @@ void __devinit cpu_cache_init(void)
|
|||
|
||||
int __weak __uncached_access(struct file *file, unsigned long addr)
|
||||
{
|
||||
if (file->f_flags & O_SYNC)
|
||||
if (file->f_flags & O_DSYNC)
|
||||
return 1;
|
||||
|
||||
return addr >= __pa(high_memory);
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
#ifndef _PARISC_FCNTL_H
|
||||
#define _PARISC_FCNTL_H
|
||||
|
||||
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
|
||||
located on an ext2 file system */
|
||||
#define O_APPEND 000000010
|
||||
#define O_BLKSEEK 000000100 /* HPUX only */
|
||||
#define O_CREAT 000000400 /* not fcntl */
|
||||
#define O_EXCL 000002000 /* not fcntl */
|
||||
#define O_LARGEFILE 000004000
|
||||
#define O_SYNC 000100000
|
||||
#define __O_SYNC 000100000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */
|
||||
#define O_NOCTTY 000400000 /* not fcntl */
|
||||
#define O_DSYNC 001000000 /* HPUX only */
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
#ifndef _SPARC_FCNTL_H
|
||||
#define _SPARC_FCNTL_H
|
||||
|
||||
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
|
||||
located on an ext2 file system */
|
||||
#define O_APPEND 0x0008
|
||||
#define FASYNC 0x0040 /* fcntl, for BSD compatibility */
|
||||
#define O_CREAT 0x0200 /* not fcntl */
|
||||
#define O_TRUNC 0x0400 /* not fcntl */
|
||||
#define O_EXCL 0x0800 /* not fcntl */
|
||||
#define O_SYNC 0x2000
|
||||
#define O_DSYNC 0x2000 /* used to be O_SYNC, see below */
|
||||
#define O_NONBLOCK 0x4000
|
||||
#if defined(__sparc__) && defined(__arch64__)
|
||||
#define O_NDELAY 0x0004
|
||||
|
@ -20,6 +18,21 @@
|
|||
#define O_DIRECT 0x100000 /* direct disk access hint */
|
||||
#define O_NOATIME 0x200000
|
||||
#define O_CLOEXEC 0x400000
|
||||
/*
|
||||
* Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
|
||||
* the O_SYNC flag. We continue to use the existing numerical value
|
||||
* for O_DSYNC semantics now, but using the correct symbolic name for it.
|
||||
* This new value is used to request true Posix O_SYNC semantics. It is
|
||||
* defined in this strange way to make sure applications compiled against
|
||||
* new headers get at least O_DSYNC semantics on older kernels.
|
||||
*
|
||||
* This has the nice side-effect that we can simply test for O_DSYNC
|
||||
* wherever we do not care if O_DSYNC or O_SYNC is used.
|
||||
*
|
||||
* Note: __O_SYNC must never be used directly.
|
||||
*/
|
||||
#define __O_SYNC 0x800000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
|
||||
#define F_GETOWN 5 /* for sockets. */
|
||||
#define F_SETOWN 6 /* for sockets. */
|
||||
|
|
|
@ -704,9 +704,8 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
|
|||
if (!range_is_allowed(pfn, size))
|
||||
return 0;
|
||||
|
||||
if (file->f_flags & O_SYNC) {
|
||||
if (file->f_flags & O_DSYNC)
|
||||
flags = _PAGE_CACHE_UC_MINUS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
/*
|
||||
|
|
|
@ -43,7 +43,7 @@ static inline int uncached_access(struct file *file, unsigned long addr)
|
|||
{
|
||||
#if defined(CONFIG_IA64)
|
||||
/*
|
||||
* On ia64, we ignore O_SYNC because we cannot tolerate memory attribute aliases.
|
||||
* On ia64, we ignore O_DSYNC because we cannot tolerate memory attribute aliases.
|
||||
*/
|
||||
return !(efi_mem_attributes(addr) & EFI_MEMORY_WB);
|
||||
#elif defined(CONFIG_MIPS)
|
||||
|
@ -56,9 +56,9 @@ static inline int uncached_access(struct file *file, unsigned long addr)
|
|||
#else
|
||||
/*
|
||||
* Accessing memory above the top the kernel knows about or through a file pointer
|
||||
* that was marked O_SYNC will be done non-cached.
|
||||
* that was marked O_DSYNC will be done non-cached.
|
||||
*/
|
||||
if (file->f_flags & O_SYNC)
|
||||
if (file->f_flags & O_DSYNC)
|
||||
return 1;
|
||||
return addr >= __pa(high_memory);
|
||||
#endif
|
||||
|
|
|
@ -1274,7 +1274,7 @@ static int do_write(struct fsg_dev *fsg)
|
|||
}
|
||||
if (fsg->cmnd[1] & 0x08) { // FUA
|
||||
spin_lock(&curlun->filp->f_lock);
|
||||
curlun->filp->f_flags |= O_SYNC;
|
||||
curlun->filp->f_flags |= O_DSYNC;
|
||||
spin_unlock(&curlun->filp->f_lock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -671,7 +671,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
|
||||
ssize_t result;
|
||||
size_t count = iov_length(iov, nr_segs);
|
||||
int ret;
|
||||
|
||||
_enter("{%x.%u},{%zu},%lu,",
|
||||
vnode->fid.vid, vnode->fid.vnode, count, nr_segs);
|
||||
|
@ -691,13 +690,6 @@ ssize_t afs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* return error values for O_SYNC and IS_SYNC() */
|
||||
if (IS_SYNC(&vnode->vfs_inode) || iocb->ki_filp->f_flags & O_SYNC) {
|
||||
ret = afs_fsync(iocb->ki_filp, dentry, 1);
|
||||
if (ret < 0)
|
||||
result = ret;
|
||||
}
|
||||
|
||||
_leave(" = %zd", result);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -909,7 +909,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
|||
unsigned long last_index;
|
||||
int will_write;
|
||||
|
||||
will_write = ((file->f_flags & O_SYNC) || IS_SYNC(inode) ||
|
||||
will_write = ((file->f_flags & O_DSYNC) || IS_SYNC(inode) ||
|
||||
(file->f_flags & O_DIRECT));
|
||||
|
||||
nrptrs = min((count + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE,
|
||||
|
@ -1076,7 +1076,7 @@ out_nolock:
|
|||
if (err)
|
||||
num_written = err;
|
||||
|
||||
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
|
||||
if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
|
||||
trans = btrfs_start_transaction(root, 1);
|
||||
ret = btrfs_log_dentry_safe(trans, root,
|
||||
file->f_dentry);
|
||||
|
|
|
@ -214,7 +214,8 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
|
|||
posix_flags |= SMB_O_EXCL;
|
||||
if (oflags & O_TRUNC)
|
||||
posix_flags |= SMB_O_TRUNC;
|
||||
if (oflags & O_SYNC)
|
||||
/* be safe and imply O_SYNC for O_DSYNC */
|
||||
if (oflags & O_DSYNC)
|
||||
posix_flags |= SMB_O_SYNC;
|
||||
if (oflags & O_DIRECTORY)
|
||||
posix_flags |= SMB_O_DIRECTORY;
|
||||
|
|
|
@ -76,8 +76,10 @@ static inline fmode_t cifs_posix_convert_flags(unsigned int flags)
|
|||
reopening a file. They had their effect on the original open */
|
||||
if (flags & O_APPEND)
|
||||
posix_flags |= (fmode_t)O_APPEND;
|
||||
if (flags & O_SYNC)
|
||||
posix_flags |= (fmode_t)O_SYNC;
|
||||
if (flags & O_DSYNC)
|
||||
posix_flags |= (fmode_t)O_DSYNC;
|
||||
if (flags & __O_SYNC)
|
||||
posix_flags |= (fmode_t)__O_SYNC;
|
||||
if (flags & O_DIRECTORY)
|
||||
posix_flags |= (fmode_t)O_DIRECTORY;
|
||||
if (flags & O_NOFOLLOW)
|
||||
|
|
|
@ -353,8 +353,8 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)
|
|||
* ext2_find_entry()
|
||||
*
|
||||
* finds an entry in the specified directory with the wanted name. It
|
||||
* returns the page in which the entry was found, and the entry itself
|
||||
* (as a parameter - res_dir). Page is returned mapped and unlocked.
|
||||
* returns the page in which the entry was found (as a parameter - res_page),
|
||||
* and the entry itself. Page is returned mapped and unlocked.
|
||||
* Entry is guaranteed to be valid.
|
||||
*/
|
||||
struct ext2_dir_entry_2 *ext2_find_entry (struct inode * dir,
|
||||
|
|
|
@ -142,7 +142,7 @@ struct dentry *ext2_get_parent(struct dentry *child);
|
|||
/* super.c */
|
||||
extern void ext2_error (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext2_warning (struct super_block *, const char *, const char *, ...)
|
||||
extern void ext2_msg(struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext2_update_dynamic_rev (struct super_block *sb);
|
||||
extern void ext2_write_super (struct super_block *);
|
||||
|
|
|
@ -137,7 +137,8 @@ static int ext2_block_to_path(struct inode *inode,
|
|||
int final = 0;
|
||||
|
||||
if (i_block < 0) {
|
||||
ext2_warning (inode->i_sb, "ext2_block_to_path", "block < 0");
|
||||
ext2_msg(inode->i_sb, KERN_WARNING,
|
||||
"warning: %s: block < 0", __func__);
|
||||
} else if (i_block < direct_blocks) {
|
||||
offsets[n++] = i_block;
|
||||
final = direct_blocks;
|
||||
|
@ -157,7 +158,8 @@ static int ext2_block_to_path(struct inode *inode,
|
|||
offsets[n++] = i_block & (ptrs - 1);
|
||||
final = ptrs;
|
||||
} else {
|
||||
ext2_warning (inode->i_sb, "ext2_block_to_path", "block > big");
|
||||
ext2_msg(inode->i_sb, KERN_WARNING,
|
||||
"warning: %s: block is too big", __func__);
|
||||
}
|
||||
if (boundary)
|
||||
*boundary = final - 1 - (i_block & (ptrs - 1));
|
||||
|
|
184
fs/ext2/super.c
184
fs/ext2/super.c
|
@ -58,27 +58,27 @@ void ext2_error (struct super_block * sb, const char * function,
|
|||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
printk(KERN_CRIT "EXT2-fs error (device %s): %s: ",sb->s_id, function);
|
||||
printk(KERN_CRIT "EXT2-fs (%s): error: %s: ", sb->s_id, function);
|
||||
vprintk(fmt, args);
|
||||
printk("\n");
|
||||
va_end(args);
|
||||
|
||||
if (test_opt(sb, ERRORS_PANIC))
|
||||
panic("EXT2-fs panic from previous error\n");
|
||||
panic("EXT2-fs: panic from previous error\n");
|
||||
if (test_opt(sb, ERRORS_RO)) {
|
||||
printk("Remounting filesystem read-only\n");
|
||||
ext2_msg(sb, KERN_CRIT,
|
||||
"error: remounting filesystem read-only");
|
||||
sb->s_flags |= MS_RDONLY;
|
||||
}
|
||||
}
|
||||
|
||||
void ext2_warning (struct super_block * sb, const char * function,
|
||||
const char * fmt, ...)
|
||||
void ext2_msg(struct super_block *sb, const char *prefix,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
printk(KERN_WARNING "EXT2-fs warning (device %s): %s: ",
|
||||
sb->s_id, function);
|
||||
printk("%sEXT2-fs (%s): ", prefix, sb->s_id);
|
||||
vprintk(fmt, args);
|
||||
printk("\n");
|
||||
va_end(args);
|
||||
|
@ -91,9 +91,9 @@ void ext2_update_dynamic_rev(struct super_block *sb)
|
|||
if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
|
||||
return;
|
||||
|
||||
ext2_warning(sb, __func__,
|
||||
"updating to rev %d because of new feature flag, "
|
||||
"running e2fsck is recommended",
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: updating to rev %d because of "
|
||||
"new feature flag, running e2fsck is recommended",
|
||||
EXT2_DYNAMIC_REV);
|
||||
|
||||
es->s_first_ino = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
|
||||
|
@ -419,10 +419,10 @@ static const match_table_t tokens = {
|
|||
{Opt_err, NULL}
|
||||
};
|
||||
|
||||
static int parse_options (char * options,
|
||||
struct ext2_sb_info *sbi)
|
||||
static int parse_options(char *options, struct super_block *sb)
|
||||
{
|
||||
char * p;
|
||||
char *p;
|
||||
struct ext2_sb_info *sbi = EXT2_SB(sb);
|
||||
substring_t args[MAX_OPT_ARGS];
|
||||
int option;
|
||||
|
||||
|
@ -505,7 +505,8 @@ static int parse_options (char * options,
|
|||
#else
|
||||
case Opt_user_xattr:
|
||||
case Opt_nouser_xattr:
|
||||
printk("EXT2 (no)user_xattr options not supported\n");
|
||||
ext2_msg(sb, KERN_INFO, "(no)user_xattr options"
|
||||
"not supported");
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
||||
|
@ -518,14 +519,15 @@ static int parse_options (char * options,
|
|||
#else
|
||||
case Opt_acl:
|
||||
case Opt_noacl:
|
||||
printk("EXT2 (no)acl options not supported\n");
|
||||
ext2_msg(sb, KERN_INFO,
|
||||
"(no)acl options not supported");
|
||||
break;
|
||||
#endif
|
||||
case Opt_xip:
|
||||
#ifdef CONFIG_EXT2_FS_XIP
|
||||
set_opt (sbi->s_mount_opt, XIP);
|
||||
#else
|
||||
printk("EXT2 xip option not supported\n");
|
||||
ext2_msg(sb, KERN_INFO, "xip option not supported");
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
@ -542,19 +544,18 @@ static int parse_options (char * options,
|
|||
case Opt_quota:
|
||||
case Opt_usrquota:
|
||||
case Opt_grpquota:
|
||||
printk(KERN_ERR
|
||||
"EXT2-fs: quota operations not supported.\n");
|
||||
|
||||
ext2_msg(sb, KERN_INFO,
|
||||
"quota operations not supported");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case Opt_reservation:
|
||||
set_opt(sbi->s_mount_opt, RESERVATION);
|
||||
printk("reservations ON\n");
|
||||
ext2_msg(sb, KERN_INFO, "reservations ON");
|
||||
break;
|
||||
case Opt_noreservation:
|
||||
clear_opt(sbi->s_mount_opt, RESERVATION);
|
||||
printk("reservations OFF\n");
|
||||
ext2_msg(sb, KERN_INFO, "reservations OFF");
|
||||
break;
|
||||
case Opt_ignore:
|
||||
break;
|
||||
|
@ -573,34 +574,40 @@ static int ext2_setup_super (struct super_block * sb,
|
|||
struct ext2_sb_info *sbi = EXT2_SB(sb);
|
||||
|
||||
if (le32_to_cpu(es->s_rev_level) > EXT2_MAX_SUPP_REV) {
|
||||
printk ("EXT2-fs warning: revision level too high, "
|
||||
"forcing read-only mode\n");
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: revision level too high, "
|
||||
"forcing read-only mode");
|
||||
res = MS_RDONLY;
|
||||
}
|
||||
if (read_only)
|
||||
return res;
|
||||
if (!(sbi->s_mount_state & EXT2_VALID_FS))
|
||||
printk ("EXT2-fs warning: mounting unchecked fs, "
|
||||
"running e2fsck is recommended\n");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: mounting unchecked fs, "
|
||||
"running e2fsck is recommended");
|
||||
else if ((sbi->s_mount_state & EXT2_ERROR_FS))
|
||||
printk ("EXT2-fs warning: mounting fs with errors, "
|
||||
"running e2fsck is recommended\n");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: mounting fs with errors, "
|
||||
"running e2fsck is recommended");
|
||||
else if ((__s16) le16_to_cpu(es->s_max_mnt_count) >= 0 &&
|
||||
le16_to_cpu(es->s_mnt_count) >=
|
||||
(unsigned short) (__s16) le16_to_cpu(es->s_max_mnt_count))
|
||||
printk ("EXT2-fs warning: maximal mount count reached, "
|
||||
"running e2fsck is recommended\n");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: maximal mount count reached, "
|
||||
"running e2fsck is recommended");
|
||||
else if (le32_to_cpu(es->s_checkinterval) &&
|
||||
(le32_to_cpu(es->s_lastcheck) + le32_to_cpu(es->s_checkinterval) <= get_seconds()))
|
||||
printk ("EXT2-fs warning: checktime reached, "
|
||||
"running e2fsck is recommended\n");
|
||||
(le32_to_cpu(es->s_lastcheck) +
|
||||
le32_to_cpu(es->s_checkinterval) <= get_seconds()))
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: checktime reached, "
|
||||
"running e2fsck is recommended");
|
||||
if (!le16_to_cpu(es->s_max_mnt_count))
|
||||
es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT);
|
||||
le16_add_cpu(&es->s_mnt_count, 1);
|
||||
ext2_write_super(sb);
|
||||
if (test_opt (sb, DEBUG))
|
||||
printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, "
|
||||
"bpg=%lu, ipg=%lu, mo=%04lx]\n",
|
||||
ext2_msg(sb, KERN_INFO, "%s, %s, bs=%lu, fs=%lu, gc=%lu, "
|
||||
"bpg=%lu, ipg=%lu, mo=%04lx]",
|
||||
EXT2FS_VERSION, EXT2FS_DATE, sb->s_blocksize,
|
||||
sbi->s_frag_size,
|
||||
sbi->s_groups_count,
|
||||
|
@ -767,7 +774,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
*/
|
||||
blocksize = sb_min_blocksize(sb, BLOCK_SIZE);
|
||||
if (!blocksize) {
|
||||
printk ("EXT2-fs: unable to set blocksize\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: unable to set blocksize");
|
||||
goto failed_sbi;
|
||||
}
|
||||
|
||||
|
@ -783,7 +790,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
}
|
||||
|
||||
if (!(bh = sb_bread(sb, logic_sb_block))) {
|
||||
printk ("EXT2-fs: unable to read superblock\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: unable to read superblock");
|
||||
goto failed_sbi;
|
||||
}
|
||||
/*
|
||||
|
@ -826,7 +833,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
set_opt(sbi->s_mount_opt, RESERVATION);
|
||||
|
||||
if (!parse_options ((char *) data, sbi))
|
||||
if (!parse_options((char *) data, sb))
|
||||
goto failed_mount;
|
||||
|
||||
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
||||
|
@ -840,8 +847,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
(EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
|
||||
EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
|
||||
EXT2_HAS_INCOMPAT_FEATURE(sb, ~0U)))
|
||||
printk("EXT2-fs warning: feature flags set on rev 0 fs, "
|
||||
"running e2fsck is recommended\n");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: feature flags set on rev 0 fs, "
|
||||
"running e2fsck is recommended");
|
||||
/*
|
||||
* Check feature flags regardless of the revision level, since we
|
||||
* previously didn't change the revision level when setting the flags,
|
||||
|
@ -849,16 +857,16 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
*/
|
||||
features = EXT2_HAS_INCOMPAT_FEATURE(sb, ~EXT2_FEATURE_INCOMPAT_SUPP);
|
||||
if (features) {
|
||||
printk("EXT2-fs: %s: couldn't mount because of "
|
||||
"unsupported optional features (%x).\n",
|
||||
sb->s_id, le32_to_cpu(features));
|
||||
ext2_msg(sb, KERN_ERR, "error: couldn't mount because of "
|
||||
"unsupported optional features (%x)",
|
||||
le32_to_cpu(features));
|
||||
goto failed_mount;
|
||||
}
|
||||
if (!(sb->s_flags & MS_RDONLY) &&
|
||||
(features = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP))){
|
||||
printk("EXT2-fs: %s: couldn't mount RDWR because of "
|
||||
"unsupported optional features (%x).\n",
|
||||
sb->s_id, le32_to_cpu(features));
|
||||
ext2_msg(sb, KERN_ERR, "error: couldn't mount RDWR because of "
|
||||
"unsupported optional features (%x)",
|
||||
le32_to_cpu(features));
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
|
@ -866,7 +874,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
if (ext2_use_xip(sb) && blocksize != PAGE_SIZE) {
|
||||
if (!silent)
|
||||
printk("XIP: Unsupported blocksize\n");
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: unsupported blocksize for xip");
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
|
@ -875,7 +884,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
brelse(bh);
|
||||
|
||||
if (!sb_set_blocksize(sb, blocksize)) {
|
||||
printk(KERN_ERR "EXT2-fs: blocksize too small for device.\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: blocksize is too small");
|
||||
goto failed_sbi;
|
||||
}
|
||||
|
||||
|
@ -883,14 +892,14 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
offset = (sb_block*BLOCK_SIZE) % blocksize;
|
||||
bh = sb_bread(sb, logic_sb_block);
|
||||
if(!bh) {
|
||||
printk("EXT2-fs: Couldn't read superblock on "
|
||||
"2nd try.\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: couldn't read"
|
||||
"superblock on 2nd try");
|
||||
goto failed_sbi;
|
||||
}
|
||||
es = (struct ext2_super_block *) (((char *)bh->b_data) + offset);
|
||||
sbi->s_es = es;
|
||||
if (es->s_magic != cpu_to_le16(EXT2_SUPER_MAGIC)) {
|
||||
printk ("EXT2-fs: Magic mismatch, very weird !\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: magic mismatch");
|
||||
goto failed_mount;
|
||||
}
|
||||
}
|
||||
|
@ -906,7 +915,8 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if ((sbi->s_inode_size < EXT2_GOOD_OLD_INODE_SIZE) ||
|
||||
!is_power_of_2(sbi->s_inode_size) ||
|
||||
(sbi->s_inode_size > blocksize)) {
|
||||
printk ("EXT2-fs: unsupported inode size: %d\n",
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: unsupported inode size: %d",
|
||||
sbi->s_inode_size);
|
||||
goto failed_mount;
|
||||
}
|
||||
|
@ -943,29 +953,33 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
if (sb->s_blocksize != bh->b_size) {
|
||||
if (!silent)
|
||||
printk ("VFS: Unsupported blocksize on dev "
|
||||
"%s.\n", sb->s_id);
|
||||
ext2_msg(sb, KERN_ERR, "error: unsupported blocksize");
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
if (sb->s_blocksize != sbi->s_frag_size) {
|
||||
printk ("EXT2-fs: fragsize %lu != blocksize %lu (not supported yet)\n",
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: fragsize %lu != blocksize %lu"
|
||||
"(not supported yet)",
|
||||
sbi->s_frag_size, sb->s_blocksize);
|
||||
goto failed_mount;
|
||||
}
|
||||
|
||||
if (sbi->s_blocks_per_group > sb->s_blocksize * 8) {
|
||||
printk ("EXT2-fs: #blocks per group too big: %lu\n",
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: #blocks per group too big: %lu",
|
||||
sbi->s_blocks_per_group);
|
||||
goto failed_mount;
|
||||
}
|
||||
if (sbi->s_frags_per_group > sb->s_blocksize * 8) {
|
||||
printk ("EXT2-fs: #fragments per group too big: %lu\n",
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: #fragments per group too big: %lu",
|
||||
sbi->s_frags_per_group);
|
||||
goto failed_mount;
|
||||
}
|
||||
if (sbi->s_inodes_per_group > sb->s_blocksize * 8) {
|
||||
printk ("EXT2-fs: #inodes per group too big: %lu\n",
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: #inodes per group too big: %lu",
|
||||
sbi->s_inodes_per_group);
|
||||
goto failed_mount;
|
||||
}
|
||||
|
@ -979,13 +993,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
EXT2_DESC_PER_BLOCK(sb);
|
||||
sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
|
||||
if (sbi->s_group_desc == NULL) {
|
||||
printk ("EXT2-fs: not enough memory\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: not enough memory");
|
||||
goto failed_mount;
|
||||
}
|
||||
bgl_lock_init(sbi->s_blockgroup_lock);
|
||||
sbi->s_debts = kcalloc(sbi->s_groups_count, sizeof(*sbi->s_debts), GFP_KERNEL);
|
||||
if (!sbi->s_debts) {
|
||||
printk ("EXT2-fs: not enough memory\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: not enough memory");
|
||||
goto failed_mount_group_desc;
|
||||
}
|
||||
for (i = 0; i < db_count; i++) {
|
||||
|
@ -994,12 +1008,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if (!sbi->s_group_desc[i]) {
|
||||
for (j = 0; j < i; j++)
|
||||
brelse (sbi->s_group_desc[j]);
|
||||
printk ("EXT2-fs: unable to read group descriptors\n");
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: unable to read group descriptors");
|
||||
goto failed_mount_group_desc;
|
||||
}
|
||||
}
|
||||
if (!ext2_check_descriptors (sb)) {
|
||||
printk ("EXT2-fs: group descriptors corrupted!\n");
|
||||
ext2_msg(sb, KERN_ERR, "group descriptors corrupted");
|
||||
goto failed_mount2;
|
||||
}
|
||||
sbi->s_gdb_count = db_count;
|
||||
|
@ -1032,7 +1047,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
ext2_count_dirs(sb));
|
||||
}
|
||||
if (err) {
|
||||
printk(KERN_ERR "EXT2-fs: insufficient memory\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: insufficient memory");
|
||||
goto failed_mount3;
|
||||
}
|
||||
/*
|
||||
|
@ -1048,27 +1063,28 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
}
|
||||
if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
|
||||
iput(root);
|
||||
printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: corrupt root inode, run e2fsck");
|
||||
goto failed_mount3;
|
||||
}
|
||||
|
||||
sb->s_root = d_alloc_root(root);
|
||||
if (!sb->s_root) {
|
||||
iput(root);
|
||||
printk(KERN_ERR "EXT2-fs: get root inode failed\n");
|
||||
ext2_msg(sb, KERN_ERR, "error: get root inode failed");
|
||||
ret = -ENOMEM;
|
||||
goto failed_mount3;
|
||||
}
|
||||
if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL))
|
||||
ext2_warning(sb, __func__,
|
||||
"mounting ext3 filesystem as ext2");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: mounting ext3 filesystem as ext2");
|
||||
ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY);
|
||||
return 0;
|
||||
|
||||
cantfind_ext2:
|
||||
if (!silent)
|
||||
printk("VFS: Can't find an ext2 filesystem on dev %s.\n",
|
||||
sb->s_id);
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"error: can't find an ext2 filesystem on dev %s.",
|
||||
sb->s_id);
|
||||
goto failed_mount;
|
||||
failed_mount3:
|
||||
percpu_counter_destroy(&sbi->s_freeblocks_counter);
|
||||
|
@ -1121,8 +1137,24 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es)
|
|||
static int ext2_sync_fs(struct super_block *sb, int wait)
|
||||
{
|
||||
struct ext2_super_block *es = EXT2_SB(sb)->s_es;
|
||||
struct buffer_head *sbh = EXT2_SB(sb)->s_sbh;
|
||||
|
||||
lock_kernel();
|
||||
if (buffer_write_io_error(sbh)) {
|
||||
/*
|
||||
* Oh, dear. A previous attempt to write the
|
||||
* superblock failed. This could happen because the
|
||||
* USB device was yanked out. Or it could happen to
|
||||
* be a transient write error and maybe the block will
|
||||
* be remapped. Nothing we can do but to retry the
|
||||
* write and hope for the best.
|
||||
*/
|
||||
ext2_msg(sb, KERN_ERR,
|
||||
"previous I/O error to superblock detected\n");
|
||||
clear_buffer_write_io_error(sbh);
|
||||
set_buffer_uptodate(sbh);
|
||||
}
|
||||
|
||||
if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
|
||||
ext2_debug("setting valid to 0\n");
|
||||
es->s_state &= cpu_to_le16(~EXT2_VALID_FS);
|
||||
|
@ -1170,7 +1202,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
|||
/*
|
||||
* Allow the "check" option to be passed as a remount option.
|
||||
*/
|
||||
if (!parse_options (data, sbi)) {
|
||||
if (!parse_options(data, sb)) {
|
||||
err = -EINVAL;
|
||||
goto restore_opts;
|
||||
}
|
||||
|
@ -1182,7 +1214,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
|||
EXT2_MOUNT_XIP if not */
|
||||
|
||||
if ((ext2_use_xip(sb)) && (sb->s_blocksize != PAGE_SIZE)) {
|
||||
printk("XIP: Unsupported blocksize\n");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: unsupported blocksize for xip");
|
||||
err = -EINVAL;
|
||||
goto restore_opts;
|
||||
}
|
||||
|
@ -1191,8 +1224,8 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
|||
if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
|
||||
(old_mount_opt & EXT2_MOUNT_XIP)) &&
|
||||
invalidate_inodes(sb)) {
|
||||
ext2_warning(sb, __func__, "refusing change of xip flag "
|
||||
"with busy inodes while remounting");
|
||||
ext2_msg(sb, KERN_WARNING, "warning: refusing change of "
|
||||
"xip flag with busy inodes while remounting");
|
||||
sbi->s_mount_opt &= ~EXT2_MOUNT_XIP;
|
||||
sbi->s_mount_opt |= old_mount_opt & EXT2_MOUNT_XIP;
|
||||
}
|
||||
|
@ -1216,9 +1249,10 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
|
|||
__le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb,
|
||||
~EXT2_FEATURE_RO_COMPAT_SUPP);
|
||||
if (ret) {
|
||||
printk("EXT2-fs: %s: couldn't remount RDWR because of "
|
||||
"unsupported optional features (%x).\n",
|
||||
sb->s_id, le32_to_cpu(ret));
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: couldn't remount RDWR because of "
|
||||
"unsupported optional features (%x).",
|
||||
le32_to_cpu(ret));
|
||||
err = -EROFS;
|
||||
goto restore_opts;
|
||||
}
|
||||
|
|
|
@ -69,8 +69,9 @@ void ext2_xip_verify_sb(struct super_block *sb)
|
|||
if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) &&
|
||||
!sb->s_bdev->bd_disk->fops->direct_access) {
|
||||
sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
|
||||
ext2_warning(sb, __func__,
|
||||
"ignoring xip option - not supported by bdev");
|
||||
ext2_msg(sb, KERN_WARNING,
|
||||
"warning: ignoring xip option - "
|
||||
"not supported by bdev");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1151,6 +1151,16 @@ static int do_journal_get_write_access(handle_t *handle,
|
|||
return ext3_journal_get_write_access(handle, bh);
|
||||
}
|
||||
|
||||
/*
|
||||
* Truncate blocks that were not used by write. We have to truncate the
|
||||
* pagecache as well so that corresponding buffers get properly unmapped.
|
||||
*/
|
||||
static void ext3_truncate_failed_write(struct inode *inode)
|
||||
{
|
||||
truncate_inode_pages(inode->i_mapping, inode->i_size);
|
||||
ext3_truncate(inode);
|
||||
}
|
||||
|
||||
static int ext3_write_begin(struct file *file, struct address_space *mapping,
|
||||
loff_t pos, unsigned len, unsigned flags,
|
||||
struct page **pagep, void **fsdata)
|
||||
|
@ -1209,7 +1219,7 @@ write_begin_failed:
|
|||
unlock_page(page);
|
||||
page_cache_release(page);
|
||||
if (pos + len > inode->i_size)
|
||||
ext3_truncate(inode);
|
||||
ext3_truncate_failed_write(inode);
|
||||
}
|
||||
if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
|
||||
goto retry;
|
||||
|
@ -1304,7 +1314,7 @@ static int ext3_ordered_write_end(struct file *file,
|
|||
page_cache_release(page);
|
||||
|
||||
if (pos + len > inode->i_size)
|
||||
ext3_truncate(inode);
|
||||
ext3_truncate_failed_write(inode);
|
||||
return ret ? ret : copied;
|
||||
}
|
||||
|
||||
|
@ -1330,7 +1340,7 @@ static int ext3_writeback_write_end(struct file *file,
|
|||
page_cache_release(page);
|
||||
|
||||
if (pos + len > inode->i_size)
|
||||
ext3_truncate(inode);
|
||||
ext3_truncate_failed_write(inode);
|
||||
return ret ? ret : copied;
|
||||
}
|
||||
|
||||
|
@ -1383,7 +1393,7 @@ static int ext3_journalled_write_end(struct file *file,
|
|||
page_cache_release(page);
|
||||
|
||||
if (pos + len > inode->i_size)
|
||||
ext3_truncate(inode);
|
||||
ext3_truncate_failed_write(inode);
|
||||
return ret ? ret : copied;
|
||||
}
|
||||
|
||||
|
|
|
@ -266,7 +266,7 @@ static int setup_new_group_blocks(struct super_block *sb,
|
|||
goto exit_bh;
|
||||
|
||||
if (IS_ERR(gdb = bclean(handle, sb, block))) {
|
||||
err = PTR_ERR(bh);
|
||||
err = PTR_ERR(gdb);
|
||||
goto exit_bh;
|
||||
}
|
||||
ext3_journal_dirty_metadata(handle, gdb);
|
||||
|
|
468
fs/ext3/super.c
468
fs/ext3/super.c
File diff suppressed because it is too large
Load Diff
|
@ -960,6 +960,10 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
|
|||
if (error)
|
||||
goto cleanup;
|
||||
|
||||
error = ext3_journal_get_write_access(handle, is.iloc.bh);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
|
||||
if (EXT3_I(inode)->i_state & EXT3_STATE_NEW) {
|
||||
struct ext3_inode *raw_inode = ext3_raw_inode(&is.iloc);
|
||||
memset(raw_inode, 0, EXT3_SB(inode->i_sb)->s_inode_size);
|
||||
|
@ -985,9 +989,6 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
|
|||
if (flags & XATTR_CREATE)
|
||||
goto cleanup;
|
||||
}
|
||||
error = ext3_journal_get_write_access(handle, is.iloc.bh);
|
||||
if (error)
|
||||
goto cleanup;
|
||||
if (!value) {
|
||||
if (!is.s.not_found)
|
||||
error = ext3_xattr_ibody_set(handle, inode, &i, &is);
|
||||
|
|
|
@ -769,9 +769,22 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
|
|||
#if defined(CONFIG_QUOTA)
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
|
||||
if (sbi->s_jquota_fmt)
|
||||
seq_printf(seq, ",jqfmt=%s",
|
||||
(sbi->s_jquota_fmt == QFMT_VFS_OLD) ? "vfsold" : "vfsv0");
|
||||
if (sbi->s_jquota_fmt) {
|
||||
char *fmtname = "";
|
||||
|
||||
switch (sbi->s_jquota_fmt) {
|
||||
case QFMT_VFS_OLD:
|
||||
fmtname = "vfsold";
|
||||
break;
|
||||
case QFMT_VFS_V0:
|
||||
fmtname = "vfsv0";
|
||||
break;
|
||||
case QFMT_VFS_V1:
|
||||
fmtname = "vfsv1";
|
||||
break;
|
||||
}
|
||||
seq_printf(seq, ",jqfmt=%s", fmtname);
|
||||
}
|
||||
|
||||
if (sbi->s_qf_names[USRQUOTA])
|
||||
seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
|
||||
|
@ -1084,9 +1097,9 @@ enum {
|
|||
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
|
||||
Opt_data_err_abort, Opt_data_err_ignore,
|
||||
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
|
||||
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
|
||||
Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err, Opt_resize,
|
||||
Opt_usrquota, Opt_grpquota, Opt_i_version,
|
||||
Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_jqfmt_vfsv1, Opt_quota,
|
||||
Opt_noquota, Opt_ignore, Opt_barrier, Opt_nobarrier, Opt_err,
|
||||
Opt_resize, Opt_usrquota, Opt_grpquota, Opt_i_version,
|
||||
Opt_stripe, Opt_delalloc, Opt_nodelalloc,
|
||||
Opt_block_validity, Opt_noblock_validity,
|
||||
Opt_inode_readahead_blks, Opt_journal_ioprio,
|
||||
|
@ -1137,6 +1150,7 @@ static const match_table_t tokens = {
|
|||
{Opt_grpjquota, "grpjquota=%s"},
|
||||
{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
|
||||
{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
|
||||
{Opt_jqfmt_vfsv1, "jqfmt=vfsv1"},
|
||||
{Opt_grpquota, "grpquota"},
|
||||
{Opt_noquota, "noquota"},
|
||||
{Opt_quota, "quota"},
|
||||
|
@ -1439,6 +1453,9 @@ clear_qf_name:
|
|||
goto set_qf_format;
|
||||
case Opt_jqfmt_vfsv0:
|
||||
qfmt = QFMT_VFS_V0;
|
||||
goto set_qf_format;
|
||||
case Opt_jqfmt_vfsv1:
|
||||
qfmt = QFMT_VFS_V1;
|
||||
set_qf_format:
|
||||
if (sb_any_quota_loaded(sb) &&
|
||||
sbi->s_jquota_fmt != qfmt) {
|
||||
|
@ -1481,6 +1498,7 @@ set_qf_format:
|
|||
case Opt_offgrpjquota:
|
||||
case Opt_jqfmt_vfsold:
|
||||
case Opt_jqfmt_vfsv0:
|
||||
case Opt_jqfmt_vfsv1:
|
||||
ext4_msg(sb, KERN_ERR,
|
||||
"journaled quota options not supported");
|
||||
break;
|
||||
|
|
|
@ -35,6 +35,260 @@ static char zisofs_sink_page[PAGE_CACHE_SIZE];
|
|||
static void *zisofs_zlib_workspace;
|
||||
static DEFINE_MUTEX(zisofs_zlib_lock);
|
||||
|
||||
/*
|
||||
* Read data of @inode from @block_start to @block_end and uncompress
|
||||
* to one zisofs block. Store the data in the @pages array with @pcount
|
||||
* entries. Start storing at offset @poffset of the first page.
|
||||
*/
|
||||
static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start,
|
||||
loff_t block_end, int pcount,
|
||||
struct page **pages, unsigned poffset,
|
||||
int *errp)
|
||||
{
|
||||
unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
|
||||
unsigned int bufsize = ISOFS_BUFFER_SIZE(inode);
|
||||
unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
|
||||
unsigned int bufmask = bufsize - 1;
|
||||
int i, block_size = block_end - block_start;
|
||||
z_stream stream = { .total_out = 0,
|
||||
.avail_in = 0,
|
||||
.avail_out = 0, };
|
||||
int zerr;
|
||||
int needblocks = (block_size + (block_start & bufmask) + bufmask)
|
||||
>> bufshift;
|
||||
int haveblocks;
|
||||
blkcnt_t blocknum;
|
||||
struct buffer_head *bhs[needblocks + 1];
|
||||
int curbh, curpage;
|
||||
|
||||
if (block_size > deflateBound(1UL << zisofs_block_shift)) {
|
||||
*errp = -EIO;
|
||||
return 0;
|
||||
}
|
||||
/* Empty block? */
|
||||
if (block_size == 0) {
|
||||
for ( i = 0 ; i < pcount ; i++ ) {
|
||||
if (!pages[i])
|
||||
continue;
|
||||
memset(page_address(pages[i]), 0, PAGE_CACHE_SIZE);
|
||||
flush_dcache_page(pages[i]);
|
||||
SetPageUptodate(pages[i]);
|
||||
}
|
||||
return ((loff_t)pcount) << PAGE_CACHE_SHIFT;
|
||||
}
|
||||
|
||||
/* Because zlib is not thread-safe, do all the I/O at the top. */
|
||||
blocknum = block_start >> bufshift;
|
||||
memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *));
|
||||
haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks);
|
||||
ll_rw_block(READ, haveblocks, bhs);
|
||||
|
||||
curbh = 0;
|
||||
curpage = 0;
|
||||
/*
|
||||
* First block is special since it may be fractional. We also wait for
|
||||
* it before grabbing the zlib mutex; odds are that the subsequent
|
||||
* blocks are going to come in in short order so we don't hold the zlib
|
||||
* mutex longer than necessary.
|
||||
*/
|
||||
|
||||
if (!bhs[0])
|
||||
goto b_eio;
|
||||
|
||||
wait_on_buffer(bhs[0]);
|
||||
if (!buffer_uptodate(bhs[0])) {
|
||||
*errp = -EIO;
|
||||
goto b_eio;
|
||||
}
|
||||
|
||||
stream.workspace = zisofs_zlib_workspace;
|
||||
mutex_lock(&zisofs_zlib_lock);
|
||||
|
||||
zerr = zlib_inflateInit(&stream);
|
||||
if (zerr != Z_OK) {
|
||||
if (zerr == Z_MEM_ERROR)
|
||||
*errp = -ENOMEM;
|
||||
else
|
||||
*errp = -EIO;
|
||||
printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
|
||||
zerr);
|
||||
goto z_eio;
|
||||
}
|
||||
|
||||
while (curpage < pcount && curbh < haveblocks &&
|
||||
zerr != Z_STREAM_END) {
|
||||
if (!stream.avail_out) {
|
||||
if (pages[curpage]) {
|
||||
stream.next_out = page_address(pages[curpage])
|
||||
+ poffset;
|
||||
stream.avail_out = PAGE_CACHE_SIZE - poffset;
|
||||
poffset = 0;
|
||||
} else {
|
||||
stream.next_out = (void *)&zisofs_sink_page;
|
||||
stream.avail_out = PAGE_CACHE_SIZE;
|
||||
}
|
||||
}
|
||||
if (!stream.avail_in) {
|
||||
wait_on_buffer(bhs[curbh]);
|
||||
if (!buffer_uptodate(bhs[curbh])) {
|
||||
*errp = -EIO;
|
||||
break;
|
||||
}
|
||||
stream.next_in = bhs[curbh]->b_data +
|
||||
(block_start & bufmask);
|
||||
stream.avail_in = min_t(unsigned, bufsize -
|
||||
(block_start & bufmask),
|
||||
block_size);
|
||||
block_size -= stream.avail_in;
|
||||
block_start = 0;
|
||||
}
|
||||
|
||||
while (stream.avail_out && stream.avail_in) {
|
||||
zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
|
||||
if (zerr == Z_BUF_ERROR && stream.avail_in == 0)
|
||||
break;
|
||||
if (zerr == Z_STREAM_END)
|
||||
break;
|
||||
if (zerr != Z_OK) {
|
||||
/* EOF, error, or trying to read beyond end of input */
|
||||
if (zerr == Z_MEM_ERROR)
|
||||
*errp = -ENOMEM;
|
||||
else {
|
||||
printk(KERN_DEBUG
|
||||
"zisofs: zisofs_inflate returned"
|
||||
" %d, inode = %lu,"
|
||||
" page idx = %d, bh idx = %d,"
|
||||
" avail_in = %d,"
|
||||
" avail_out = %d\n",
|
||||
zerr, inode->i_ino, curpage,
|
||||
curbh, stream.avail_in,
|
||||
stream.avail_out);
|
||||
*errp = -EIO;
|
||||
}
|
||||
goto inflate_out;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stream.avail_out) {
|
||||
/* This page completed */
|
||||
if (pages[curpage]) {
|
||||
flush_dcache_page(pages[curpage]);
|
||||
SetPageUptodate(pages[curpage]);
|
||||
}
|
||||
curpage++;
|
||||
}
|
||||
if (!stream.avail_in)
|
||||
curbh++;
|
||||
}
|
||||
inflate_out:
|
||||
zlib_inflateEnd(&stream);
|
||||
|
||||
z_eio:
|
||||
mutex_unlock(&zisofs_zlib_lock);
|
||||
|
||||
b_eio:
|
||||
for (i = 0; i < haveblocks; i++)
|
||||
brelse(bhs[i]);
|
||||
return stream.total_out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Uncompress data so that pages[full_page] is fully uptodate and possibly
|
||||
* fills in other pages if we have data for them.
|
||||
*/
|
||||
static int zisofs_fill_pages(struct inode *inode, int full_page, int pcount,
|
||||
struct page **pages)
|
||||
{
|
||||
loff_t start_off, end_off;
|
||||
loff_t block_start, block_end;
|
||||
unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
|
||||
unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
|
||||
unsigned int blockptr;
|
||||
loff_t poffset = 0;
|
||||
blkcnt_t cstart_block, cend_block;
|
||||
struct buffer_head *bh;
|
||||
unsigned int blkbits = ISOFS_BUFFER_BITS(inode);
|
||||
unsigned int blksize = 1 << blkbits;
|
||||
int err;
|
||||
loff_t ret;
|
||||
|
||||
BUG_ON(!pages[full_page]);
|
||||
|
||||
/*
|
||||
* We want to read at least 'full_page' page. Because we have to
|
||||
* uncompress the whole compression block anyway, fill the surrounding
|
||||
* pages with the data we have anyway...
|
||||
*/
|
||||
start_off = page_offset(pages[full_page]);
|
||||
end_off = min_t(loff_t, start_off + PAGE_CACHE_SIZE, inode->i_size);
|
||||
|
||||
cstart_block = start_off >> zisofs_block_shift;
|
||||
cend_block = (end_off + (1 << zisofs_block_shift) - 1)
|
||||
>> zisofs_block_shift;
|
||||
|
||||
WARN_ON(start_off - (full_page << PAGE_CACHE_SHIFT) !=
|
||||
((cstart_block << zisofs_block_shift) & PAGE_CACHE_MASK));
|
||||
|
||||
/* Find the pointer to this specific chunk */
|
||||
/* Note: we're not using isonum_731() here because the data is known aligned */
|
||||
/* Note: header_size is in 32-bit words (4 bytes) */
|
||||
blockptr = (header_size + cstart_block) << 2;
|
||||
bh = isofs_bread(inode, blockptr >> blkbits);
|
||||
if (!bh)
|
||||
return -EIO;
|
||||
block_start = le32_to_cpu(*(__le32 *)
|
||||
(bh->b_data + (blockptr & (blksize - 1))));
|
||||
|
||||
while (cstart_block < cend_block && pcount > 0) {
|
||||
/* Load end of the compressed block in the file */
|
||||
blockptr += 4;
|
||||
/* Traversed to next block? */
|
||||
if (!(blockptr & (blksize - 1))) {
|
||||
brelse(bh);
|
||||
|
||||
bh = isofs_bread(inode, blockptr >> blkbits);
|
||||
if (!bh)
|
||||
return -EIO;
|
||||
}
|
||||
block_end = le32_to_cpu(*(__le32 *)
|
||||
(bh->b_data + (blockptr & (blksize - 1))));
|
||||
if (block_start > block_end) {
|
||||
brelse(bh);
|
||||
return -EIO;
|
||||
}
|
||||
err = 0;
|
||||
ret = zisofs_uncompress_block(inode, block_start, block_end,
|
||||
pcount, pages, poffset, &err);
|
||||
poffset += ret;
|
||||
pages += poffset >> PAGE_CACHE_SHIFT;
|
||||
pcount -= poffset >> PAGE_CACHE_SHIFT;
|
||||
full_page -= poffset >> PAGE_CACHE_SHIFT;
|
||||
poffset &= ~PAGE_CACHE_MASK;
|
||||
|
||||
if (err) {
|
||||
brelse(bh);
|
||||
/*
|
||||
* Did we finish reading the page we really wanted
|
||||
* to read?
|
||||
*/
|
||||
if (full_page < 0)
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
block_start = block_end;
|
||||
cstart_block++;
|
||||
}
|
||||
|
||||
if (poffset && *pages) {
|
||||
memset(page_address(*pages) + poffset, 0,
|
||||
PAGE_CACHE_SIZE - poffset);
|
||||
flush_dcache_page(*pages);
|
||||
SetPageUptodate(*pages);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When decompressing, we typically obtain more than one page
|
||||
* per reference. We inject the additional pages into the page
|
||||
|
@ -44,278 +298,61 @@ static int zisofs_readpage(struct file *file, struct page *page)
|
|||
{
|
||||
struct inode *inode = file->f_path.dentry->d_inode;
|
||||
struct address_space *mapping = inode->i_mapping;
|
||||
unsigned int maxpage, xpage, fpage, blockindex;
|
||||
unsigned long offset;
|
||||
unsigned long blockptr, blockendptr, cstart, cend, csize;
|
||||
struct buffer_head *bh, *ptrbh[2];
|
||||
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
|
||||
unsigned int bufshift = ISOFS_BUFFER_BITS(inode);
|
||||
unsigned long bufmask = bufsize - 1;
|
||||
int err = -EIO;
|
||||
int i;
|
||||
unsigned int header_size = ISOFS_I(inode)->i_format_parm[0];
|
||||
int err;
|
||||
int i, pcount, full_page;
|
||||
unsigned int zisofs_block_shift = ISOFS_I(inode)->i_format_parm[1];
|
||||
/* unsigned long zisofs_block_size = 1UL << zisofs_block_shift; */
|
||||
unsigned int zisofs_block_page_shift = zisofs_block_shift-PAGE_CACHE_SHIFT;
|
||||
unsigned long zisofs_block_pages = 1UL << zisofs_block_page_shift;
|
||||
unsigned long zisofs_block_page_mask = zisofs_block_pages-1;
|
||||
struct page *pages[zisofs_block_pages];
|
||||
unsigned long index = page->index;
|
||||
int indexblocks;
|
||||
|
||||
/* We have already been given one page, this is the one
|
||||
we must do. */
|
||||
xpage = index & zisofs_block_page_mask;
|
||||
pages[xpage] = page;
|
||||
|
||||
/* The remaining pages need to be allocated and inserted */
|
||||
offset = index & ~zisofs_block_page_mask;
|
||||
blockindex = offset >> zisofs_block_page_shift;
|
||||
maxpage = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||
unsigned int zisofs_pages_per_cblock =
|
||||
PAGE_CACHE_SHIFT <= zisofs_block_shift ?
|
||||
(1 << (zisofs_block_shift - PAGE_CACHE_SHIFT)) : 0;
|
||||
struct page *pages[max_t(unsigned, zisofs_pages_per_cblock, 1)];
|
||||
pgoff_t index = page->index, end_index;
|
||||
|
||||
end_index = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||
/*
|
||||
* If this page is wholly outside i_size we just return zero;
|
||||
* do_generic_file_read() will handle this for us
|
||||
*/
|
||||
if (page->index >= maxpage) {
|
||||
if (index >= end_index) {
|
||||
SetPageUptodate(page);
|
||||
unlock_page(page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
maxpage = min(zisofs_block_pages, maxpage-offset);
|
||||
|
||||
for ( i = 0 ; i < maxpage ; i++, offset++ ) {
|
||||
if ( i != xpage ) {
|
||||
pages[i] = grab_cache_page_nowait(mapping, offset);
|
||||
}
|
||||
page = pages[i];
|
||||
if ( page ) {
|
||||
ClearPageError(page);
|
||||
kmap(page);
|
||||
}
|
||||
}
|
||||
|
||||
/* This is the last page filled, plus one; used in case of abort. */
|
||||
fpage = 0;
|
||||
|
||||
/* Find the pointer to this specific chunk */
|
||||
/* Note: we're not using isonum_731() here because the data is known aligned */
|
||||
/* Note: header_size is in 32-bit words (4 bytes) */
|
||||
blockptr = (header_size + blockindex) << 2;
|
||||
blockendptr = blockptr + 4;
|
||||
|
||||
indexblocks = ((blockptr^blockendptr) >> bufshift) ? 2 : 1;
|
||||
ptrbh[0] = ptrbh[1] = NULL;
|
||||
|
||||
if ( isofs_get_blocks(inode, blockptr >> bufshift, ptrbh, indexblocks) != indexblocks ) {
|
||||
if ( ptrbh[0] ) brelse(ptrbh[0]);
|
||||
printk(KERN_DEBUG "zisofs: Null buffer on reading block table, inode = %lu, block = %lu\n",
|
||||
inode->i_ino, blockptr >> bufshift);
|
||||
goto eio;
|
||||
}
|
||||
ll_rw_block(READ, indexblocks, ptrbh);
|
||||
|
||||
bh = ptrbh[0];
|
||||
if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
|
||||
printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
|
||||
inode->i_ino, blockptr >> bufshift);
|
||||
if ( ptrbh[1] )
|
||||
brelse(ptrbh[1]);
|
||||
goto eio;
|
||||
}
|
||||
cstart = le32_to_cpu(*(__le32 *)(bh->b_data + (blockptr & bufmask)));
|
||||
|
||||
if ( indexblocks == 2 ) {
|
||||
/* We just crossed a block boundary. Switch to the next block */
|
||||
brelse(bh);
|
||||
bh = ptrbh[1];
|
||||
if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
|
||||
printk(KERN_DEBUG "zisofs: Failed to read block table, inode = %lu, block = %lu\n",
|
||||
inode->i_ino, blockendptr >> bufshift);
|
||||
goto eio;
|
||||
}
|
||||
}
|
||||
cend = le32_to_cpu(*(__le32 *)(bh->b_data + (blockendptr & bufmask)));
|
||||
brelse(bh);
|
||||
|
||||
if (cstart > cend)
|
||||
goto eio;
|
||||
|
||||
csize = cend-cstart;
|
||||
|
||||
if (csize > deflateBound(1UL << zisofs_block_shift))
|
||||
goto eio;
|
||||
|
||||
/* Now page[] contains an array of pages, any of which can be NULL,
|
||||
and the locks on which we hold. We should now read the data and
|
||||
release the pages. If the pages are NULL the decompressed data
|
||||
for that particular page should be discarded. */
|
||||
|
||||
if ( csize == 0 ) {
|
||||
/* This data block is empty. */
|
||||
|
||||
for ( fpage = 0 ; fpage < maxpage ; fpage++ ) {
|
||||
if ( (page = pages[fpage]) != NULL ) {
|
||||
memset(page_address(page), 0, PAGE_CACHE_SIZE);
|
||||
|
||||
flush_dcache_page(page);
|
||||
SetPageUptodate(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
if ( fpage == xpage )
|
||||
err = 0; /* The critical page */
|
||||
else
|
||||
page_cache_release(page);
|
||||
}
|
||||
}
|
||||
if (PAGE_CACHE_SHIFT <= zisofs_block_shift) {
|
||||
/* We have already been given one page, this is the one
|
||||
we must do. */
|
||||
full_page = index & (zisofs_pages_per_cblock - 1);
|
||||
pcount = min_t(int, zisofs_pages_per_cblock,
|
||||
end_index - (index & ~(zisofs_pages_per_cblock - 1)));
|
||||
index -= full_page;
|
||||
} else {
|
||||
/* This data block is compressed. */
|
||||
z_stream stream;
|
||||
int bail = 0, left_out = -1;
|
||||
int zerr;
|
||||
int needblocks = (csize + (cstart & bufmask) + bufmask) >> bufshift;
|
||||
int haveblocks;
|
||||
struct buffer_head *bhs[needblocks+1];
|
||||
struct buffer_head **bhptr;
|
||||
full_page = 0;
|
||||
pcount = 1;
|
||||
}
|
||||
pages[full_page] = page;
|
||||
|
||||
/* Because zlib is not thread-safe, do all the I/O at the top. */
|
||||
|
||||
blockptr = cstart >> bufshift;
|
||||
memset(bhs, 0, (needblocks+1)*sizeof(struct buffer_head *));
|
||||
haveblocks = isofs_get_blocks(inode, blockptr, bhs, needblocks);
|
||||
ll_rw_block(READ, haveblocks, bhs);
|
||||
|
||||
bhptr = &bhs[0];
|
||||
bh = *bhptr++;
|
||||
|
||||
/* First block is special since it may be fractional.
|
||||
We also wait for it before grabbing the zlib
|
||||
mutex; odds are that the subsequent blocks are
|
||||
going to come in in short order so we don't hold
|
||||
the zlib mutex longer than necessary. */
|
||||
|
||||
if ( !bh || (wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
|
||||
printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
|
||||
fpage, xpage, csize);
|
||||
goto b_eio;
|
||||
}
|
||||
stream.next_in = bh->b_data + (cstart & bufmask);
|
||||
stream.avail_in = min(bufsize-(cstart & bufmask), csize);
|
||||
csize -= stream.avail_in;
|
||||
|
||||
stream.workspace = zisofs_zlib_workspace;
|
||||
mutex_lock(&zisofs_zlib_lock);
|
||||
|
||||
zerr = zlib_inflateInit(&stream);
|
||||
if ( zerr != Z_OK ) {
|
||||
if ( err && zerr == Z_MEM_ERROR )
|
||||
err = -ENOMEM;
|
||||
printk(KERN_DEBUG "zisofs: zisofs_inflateInit returned %d\n",
|
||||
zerr);
|
||||
goto z_eio;
|
||||
}
|
||||
|
||||
while ( !bail && fpage < maxpage ) {
|
||||
page = pages[fpage];
|
||||
if ( page )
|
||||
stream.next_out = page_address(page);
|
||||
else
|
||||
stream.next_out = (void *)&zisofs_sink_page;
|
||||
stream.avail_out = PAGE_CACHE_SIZE;
|
||||
|
||||
while ( stream.avail_out ) {
|
||||
int ao, ai;
|
||||
if ( stream.avail_in == 0 && left_out ) {
|
||||
if ( !csize ) {
|
||||
printk(KERN_WARNING "zisofs: ZF read beyond end of input\n");
|
||||
bail = 1;
|
||||
break;
|
||||
} else {
|
||||
bh = *bhptr++;
|
||||
if ( !bh ||
|
||||
(wait_on_buffer(bh), !buffer_uptodate(bh)) ) {
|
||||
/* Reached an EIO */
|
||||
printk(KERN_DEBUG "zisofs: Hit null buffer, fpage = %d, xpage = %d, csize = %ld\n",
|
||||
fpage, xpage, csize);
|
||||
|
||||
bail = 1;
|
||||
break;
|
||||
}
|
||||
stream.next_in = bh->b_data;
|
||||
stream.avail_in = min(csize,bufsize);
|
||||
csize -= stream.avail_in;
|
||||
}
|
||||
}
|
||||
ao = stream.avail_out; ai = stream.avail_in;
|
||||
zerr = zlib_inflate(&stream, Z_SYNC_FLUSH);
|
||||
left_out = stream.avail_out;
|
||||
if ( zerr == Z_BUF_ERROR && stream.avail_in == 0 )
|
||||
continue;
|
||||
if ( zerr != Z_OK ) {
|
||||
/* EOF, error, or trying to read beyond end of input */
|
||||
if ( err && zerr == Z_MEM_ERROR )
|
||||
err = -ENOMEM;
|
||||
if ( zerr != Z_STREAM_END )
|
||||
printk(KERN_DEBUG "zisofs: zisofs_inflate returned %d, inode = %lu, index = %lu, fpage = %d, xpage = %d, avail_in = %d, avail_out = %d, ai = %d, ao = %d\n",
|
||||
zerr, inode->i_ino, index,
|
||||
fpage, xpage,
|
||||
stream.avail_in, stream.avail_out,
|
||||
ai, ao);
|
||||
bail = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( stream.avail_out && zerr == Z_STREAM_END ) {
|
||||
/* Fractional page written before EOF. This may
|
||||
be the last page in the file. */
|
||||
memset(stream.next_out, 0, stream.avail_out);
|
||||
stream.avail_out = 0;
|
||||
}
|
||||
|
||||
if ( !stream.avail_out ) {
|
||||
/* This page completed */
|
||||
if ( page ) {
|
||||
flush_dcache_page(page);
|
||||
SetPageUptodate(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
if ( fpage == xpage )
|
||||
err = 0; /* The critical page */
|
||||
else
|
||||
page_cache_release(page);
|
||||
}
|
||||
fpage++;
|
||||
}
|
||||
}
|
||||
zlib_inflateEnd(&stream);
|
||||
|
||||
z_eio:
|
||||
mutex_unlock(&zisofs_zlib_lock);
|
||||
|
||||
b_eio:
|
||||
for ( i = 0 ; i < haveblocks ; i++ ) {
|
||||
if ( bhs[i] )
|
||||
brelse(bhs[i]);
|
||||
for (i = 0; i < pcount; i++, index++) {
|
||||
if (i != full_page)
|
||||
pages[i] = grab_cache_page_nowait(mapping, index);
|
||||
if (pages[i]) {
|
||||
ClearPageError(pages[i]);
|
||||
kmap(pages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
eio:
|
||||
err = zisofs_fill_pages(inode, full_page, pcount, pages);
|
||||
|
||||
/* Release any residual pages, do not SetPageUptodate */
|
||||
while ( fpage < maxpage ) {
|
||||
page = pages[fpage];
|
||||
if ( page ) {
|
||||
flush_dcache_page(page);
|
||||
if ( fpage == xpage )
|
||||
SetPageError(page);
|
||||
kunmap(page);
|
||||
unlock_page(page);
|
||||
if ( fpage != xpage )
|
||||
page_cache_release(page);
|
||||
for (i = 0; i < pcount; i++) {
|
||||
if (pages[i]) {
|
||||
flush_dcache_page(pages[i]);
|
||||
if (i == full_page && err)
|
||||
SetPageError(pages[i]);
|
||||
kunmap(pages[i]);
|
||||
unlock_page(pages[i]);
|
||||
if (i != full_page)
|
||||
page_cache_release(pages[i]);
|
||||
}
|
||||
fpage++;
|
||||
}
|
||||
|
||||
/* At this point, err contains 0 or -EIO depending on the "critical" page */
|
||||
|
|
|
@ -518,8 +518,7 @@ repeat:
|
|||
if (algo == SIG('p', 'z')) {
|
||||
int block_shift =
|
||||
isonum_711(&rr->u.ZF.parms[1]);
|
||||
if (block_shift < PAGE_CACHE_SHIFT
|
||||
|| block_shift > 17) {
|
||||
if (block_shift > 17) {
|
||||
printk(KERN_WARNING "isofs: "
|
||||
"Can't handle ZF block "
|
||||
"size of 2^%d\n",
|
||||
|
|
|
@ -286,7 +286,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
|
|||
if (err) {
|
||||
/*
|
||||
* Because AS_EIO is cleared by
|
||||
* wait_on_page_writeback_range(), set it again so
|
||||
* filemap_fdatawait_range(), set it again so
|
||||
* that user process can get -EIO from fsync().
|
||||
*/
|
||||
set_bit(AS_EIO,
|
||||
|
|
|
@ -1656,6 +1656,15 @@ struct file *do_filp_open(int dfd, const char *pathname,
|
|||
int will_write;
|
||||
int flag = open_to_namei_flags(open_flag);
|
||||
|
||||
/*
|
||||
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
|
||||
* check for O_DSYNC if the need any syncing at all we enforce it's
|
||||
* always set instead of having to deal with possibly weird behaviour
|
||||
* for malicious applications setting only __O_SYNC.
|
||||
*/
|
||||
if (open_flag & __O_SYNC)
|
||||
open_flag |= O_DSYNC;
|
||||
|
||||
if (!acc_mode)
|
||||
acc_mode = MAY_OPEN | ACC_MODE(flag);
|
||||
|
||||
|
|
|
@ -581,7 +581,7 @@ static int nfs_need_sync_write(struct file *filp, struct inode *inode)
|
|||
{
|
||||
struct nfs_open_context *ctx;
|
||||
|
||||
if (IS_SYNC(inode) || (filp->f_flags & O_SYNC))
|
||||
if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC))
|
||||
return 1;
|
||||
ctx = nfs_file_open_context(filp);
|
||||
if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags))
|
||||
|
@ -622,7 +622,7 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
|
||||
nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, count);
|
||||
result = generic_file_aio_write(iocb, iov, nr_segs, pos);
|
||||
/* Return error values for O_SYNC and IS_SYNC() */
|
||||
/* Return error values for O_DSYNC and IS_SYNC() */
|
||||
if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) {
|
||||
int err = nfs_do_fsync(nfs_file_open_context(iocb->ki_filp), inode);
|
||||
if (err < 0)
|
||||
|
|
|
@ -774,7 +774,7 @@ int nfs_updatepage(struct file *file, struct page *page,
|
|||
*/
|
||||
if (nfs_write_pageuptodate(page, inode) &&
|
||||
inode->i_flock == NULL &&
|
||||
!(file->f_flags & O_SYNC)) {
|
||||
!(file->f_flags & O_DSYNC)) {
|
||||
count = max(count + offset, nfs_page_length(page));
|
||||
offset = 0;
|
||||
}
|
||||
|
|
|
@ -2006,7 +2006,7 @@ out_dio:
|
|||
/* buffered aio wouldn't have proper lock coverage today */
|
||||
BUG_ON(ret == -EIOCBQUEUED && !(file->f_flags & O_DIRECT));
|
||||
|
||||
if ((file->f_flags & O_SYNC && !direct_io) || IS_SYNC(inode)) {
|
||||
if ((file->f_flags & O_DSYNC && !direct_io) || IS_SYNC(inode)) {
|
||||
ret = filemap_fdatawrite_range(file->f_mapping, pos,
|
||||
pos + count - 1);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -17,10 +17,6 @@
|
|||
|
||||
#include "ocfs2.h"
|
||||
|
||||
/* Common stuff */
|
||||
/* id number of quota format */
|
||||
#define QFMT_OCFS2 3
|
||||
|
||||
/*
|
||||
* In-memory structures
|
||||
*/
|
||||
|
|
|
@ -1325,7 +1325,7 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
static struct quota_format_ops ocfs2_format_ops = {
|
||||
static const struct quota_format_ops ocfs2_format_ops = {
|
||||
.check_quota_file = ocfs2_local_check_quota_file,
|
||||
.read_file_info = ocfs2_local_read_info,
|
||||
.write_file_info = ocfs2_global_write_info,
|
||||
|
|
|
@ -46,12 +46,14 @@ config QFMT_V1
|
|||
format say Y here.
|
||||
|
||||
config QFMT_V2
|
||||
tristate "Quota format v2 support"
|
||||
tristate "Quota format vfsv0 and vfsv1 support"
|
||||
depends on QUOTA
|
||||
select QUOTA_TREE
|
||||
help
|
||||
This quota format allows using quotas with 32-bit UIDs/GIDs. If you
|
||||
need this functionality say Y here.
|
||||
This config option enables kernel support for vfsv0 and vfsv1 quota
|
||||
formats. Both these formats support 32-bit UIDs/GIDs and vfsv1 format
|
||||
also supports 64-bit inode and block quota limits. If you need this
|
||||
functionality say Y here.
|
||||
|
||||
config QUOTACTL
|
||||
bool
|
||||
|
|
|
@ -2164,7 +2164,9 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
|
|||
struct dentry *dentry;
|
||||
int error;
|
||||
|
||||
mutex_lock(&sb->s_root->d_inode->i_mutex);
|
||||
dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
|
||||
mutex_unlock(&sb->s_root->d_inode->i_mutex);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct quota_format_ops v1_format_ops = {
|
||||
static const struct quota_format_ops v1_format_ops = {
|
||||
.check_quota_file = v1_check_quota_file,
|
||||
.read_file_info = v1_read_file_info,
|
||||
.write_file_info = v1_write_file_info,
|
||||
|
|
|
@ -23,14 +23,23 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
#define __QUOTA_V2_PARANOIA
|
||||
|
||||
static void v2_mem2diskdqb(void *dp, struct dquot *dquot);
|
||||
static void v2_disk2memdqb(struct dquot *dquot, void *dp);
|
||||
static int v2_is_id(void *dp, struct dquot *dquot);
|
||||
static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot);
|
||||
static void v2r0_disk2memdqb(struct dquot *dquot, void *dp);
|
||||
static int v2r0_is_id(void *dp, struct dquot *dquot);
|
||||
static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot);
|
||||
static void v2r1_disk2memdqb(struct dquot *dquot, void *dp);
|
||||
static int v2r1_is_id(void *dp, struct dquot *dquot);
|
||||
|
||||
static struct qtree_fmt_operations v2_qtree_ops = {
|
||||
.mem2disk_dqblk = v2_mem2diskdqb,
|
||||
.disk2mem_dqblk = v2_disk2memdqb,
|
||||
.is_id = v2_is_id,
|
||||
static struct qtree_fmt_operations v2r0_qtree_ops = {
|
||||
.mem2disk_dqblk = v2r0_mem2diskdqb,
|
||||
.disk2mem_dqblk = v2r0_disk2memdqb,
|
||||
.is_id = v2r0_is_id,
|
||||
};
|
||||
|
||||
static struct qtree_fmt_operations v2r1_qtree_ops = {
|
||||
.mem2disk_dqblk = v2r1_mem2diskdqb,
|
||||
.disk2mem_dqblk = v2r1_disk2memdqb,
|
||||
.is_id = v2r1_is_id,
|
||||
};
|
||||
|
||||
#define QUOTABLOCK_BITS 10
|
||||
|
@ -46,23 +55,33 @@ static inline qsize_t v2_qbtos(qsize_t blocks)
|
|||
return blocks << QUOTABLOCK_BITS;
|
||||
}
|
||||
|
||||
static int v2_read_header(struct super_block *sb, int type,
|
||||
struct v2_disk_dqheader *dqhead)
|
||||
{
|
||||
ssize_t size;
|
||||
|
||||
size = sb->s_op->quota_read(sb, type, (char *)dqhead,
|
||||
sizeof(struct v2_disk_dqheader), 0);
|
||||
if (size != sizeof(struct v2_disk_dqheader)) {
|
||||
printk(KERN_WARNING "quota_v2: Failed header read:"
|
||||
" expected=%zd got=%zd\n",
|
||||
sizeof(struct v2_disk_dqheader), size);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check whether given file is really vfsv0 quotafile */
|
||||
static int v2_check_quota_file(struct super_block *sb, int type)
|
||||
{
|
||||
struct v2_disk_dqheader dqhead;
|
||||
ssize_t size;
|
||||
static const uint quota_magics[] = V2_INITQMAGICS;
|
||||
static const uint quota_versions[] = V2_INITQVERSIONS;
|
||||
|
||||
size = sb->s_op->quota_read(sb, type, (char *)&dqhead,
|
||||
sizeof(struct v2_disk_dqheader), 0);
|
||||
if (size != sizeof(struct v2_disk_dqheader)) {
|
||||
printk("quota_v2: failed read expected=%zd got=%zd\n",
|
||||
sizeof(struct v2_disk_dqheader), size);
|
||||
if (!v2_read_header(sb, type, &dqhead))
|
||||
return 0;
|
||||
}
|
||||
if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
|
||||
le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
|
||||
le32_to_cpu(dqhead.dqh_version) > quota_versions[type])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -71,14 +90,20 @@ static int v2_check_quota_file(struct super_block *sb, int type)
|
|||
static int v2_read_file_info(struct super_block *sb, int type)
|
||||
{
|
||||
struct v2_disk_dqinfo dinfo;
|
||||
struct v2_disk_dqheader dqhead;
|
||||
struct mem_dqinfo *info = sb_dqinfo(sb, type);
|
||||
struct qtree_mem_dqinfo *qinfo;
|
||||
ssize_t size;
|
||||
unsigned int version;
|
||||
|
||||
if (!v2_read_header(sb, type, &dqhead))
|
||||
return 0;
|
||||
version = le32_to_cpu(dqhead.dqh_version);
|
||||
|
||||
size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
|
||||
sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
|
||||
if (size != sizeof(struct v2_disk_dqinfo)) {
|
||||
printk(KERN_WARNING "Can't read info structure on device %s.\n",
|
||||
printk(KERN_WARNING "quota_v2: Can't read info structure on device %s.\n",
|
||||
sb->s_id);
|
||||
return -1;
|
||||
}
|
||||
|
@ -89,9 +114,15 @@ static int v2_read_file_info(struct super_block *sb, int type)
|
|||
return -1;
|
||||
}
|
||||
qinfo = info->dqi_priv;
|
||||
/* limits are stored as unsigned 32-bit data */
|
||||
info->dqi_maxblimit = 0xffffffff;
|
||||
info->dqi_maxilimit = 0xffffffff;
|
||||
if (version == 0) {
|
||||
/* limits are stored as unsigned 32-bit data */
|
||||
info->dqi_maxblimit = 0xffffffff;
|
||||
info->dqi_maxilimit = 0xffffffff;
|
||||
} else {
|
||||
/* used space is stored as unsigned 64-bit value */
|
||||
info->dqi_maxblimit = 0xffffffffffffffff; /* 2^64-1 */
|
||||
info->dqi_maxilimit = 0xffffffffffffffff;
|
||||
}
|
||||
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
|
||||
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
|
||||
info->dqi_flags = le32_to_cpu(dinfo.dqi_flags);
|
||||
|
@ -103,8 +134,13 @@ static int v2_read_file_info(struct super_block *sb, int type)
|
|||
qinfo->dqi_blocksize_bits = V2_DQBLKSIZE_BITS;
|
||||
qinfo->dqi_usable_bs = 1 << V2_DQBLKSIZE_BITS;
|
||||
qinfo->dqi_qtree_depth = qtree_depth(qinfo);
|
||||
qinfo->dqi_entry_size = sizeof(struct v2_disk_dqblk);
|
||||
qinfo->dqi_ops = &v2_qtree_ops;
|
||||
if (version == 0) {
|
||||
qinfo->dqi_entry_size = sizeof(struct v2r0_disk_dqblk);
|
||||
qinfo->dqi_ops = &v2r0_qtree_ops;
|
||||
} else {
|
||||
qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
|
||||
qinfo->dqi_ops = &v2r1_qtree_ops;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -135,9 +171,9 @@ static int v2_write_file_info(struct super_block *sb, int type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void v2_disk2memdqb(struct dquot *dquot, void *dp)
|
||||
static void v2r0_disk2memdqb(struct dquot *dquot, void *dp)
|
||||
{
|
||||
struct v2_disk_dqblk *d = dp, empty;
|
||||
struct v2r0_disk_dqblk *d = dp, empty;
|
||||
struct mem_dqblk *m = &dquot->dq_dqb;
|
||||
|
||||
m->dqb_ihardlimit = le32_to_cpu(d->dqb_ihardlimit);
|
||||
|
@ -149,15 +185,15 @@ static void v2_disk2memdqb(struct dquot *dquot, void *dp)
|
|||
m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
|
||||
m->dqb_btime = le64_to_cpu(d->dqb_btime);
|
||||
/* We need to escape back all-zero structure */
|
||||
memset(&empty, 0, sizeof(struct v2_disk_dqblk));
|
||||
memset(&empty, 0, sizeof(struct v2r0_disk_dqblk));
|
||||
empty.dqb_itime = cpu_to_le64(1);
|
||||
if (!memcmp(&empty, dp, sizeof(struct v2_disk_dqblk)))
|
||||
if (!memcmp(&empty, dp, sizeof(struct v2r0_disk_dqblk)))
|
||||
m->dqb_itime = 0;
|
||||
}
|
||||
|
||||
static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
|
||||
static void v2r0_mem2diskdqb(void *dp, struct dquot *dquot)
|
||||
{
|
||||
struct v2_disk_dqblk *d = dp;
|
||||
struct v2r0_disk_dqblk *d = dp;
|
||||
struct mem_dqblk *m = &dquot->dq_dqb;
|
||||
struct qtree_mem_dqinfo *info =
|
||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||
|
@ -175,9 +211,60 @@ static void v2_mem2diskdqb(void *dp, struct dquot *dquot)
|
|||
d->dqb_itime = cpu_to_le64(1);
|
||||
}
|
||||
|
||||
static int v2_is_id(void *dp, struct dquot *dquot)
|
||||
static int v2r0_is_id(void *dp, struct dquot *dquot)
|
||||
{
|
||||
struct v2_disk_dqblk *d = dp;
|
||||
struct v2r0_disk_dqblk *d = dp;
|
||||
struct qtree_mem_dqinfo *info =
|
||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||
|
||||
if (qtree_entry_unused(info, dp))
|
||||
return 0;
|
||||
return le32_to_cpu(d->dqb_id) == dquot->dq_id;
|
||||
}
|
||||
|
||||
static void v2r1_disk2memdqb(struct dquot *dquot, void *dp)
|
||||
{
|
||||
struct v2r1_disk_dqblk *d = dp, empty;
|
||||
struct mem_dqblk *m = &dquot->dq_dqb;
|
||||
|
||||
m->dqb_ihardlimit = le64_to_cpu(d->dqb_ihardlimit);
|
||||
m->dqb_isoftlimit = le64_to_cpu(d->dqb_isoftlimit);
|
||||
m->dqb_curinodes = le64_to_cpu(d->dqb_curinodes);
|
||||
m->dqb_itime = le64_to_cpu(d->dqb_itime);
|
||||
m->dqb_bhardlimit = v2_qbtos(le64_to_cpu(d->dqb_bhardlimit));
|
||||
m->dqb_bsoftlimit = v2_qbtos(le64_to_cpu(d->dqb_bsoftlimit));
|
||||
m->dqb_curspace = le64_to_cpu(d->dqb_curspace);
|
||||
m->dqb_btime = le64_to_cpu(d->dqb_btime);
|
||||
/* We need to escape back all-zero structure */
|
||||
memset(&empty, 0, sizeof(struct v2r1_disk_dqblk));
|
||||
empty.dqb_itime = cpu_to_le64(1);
|
||||
if (!memcmp(&empty, dp, sizeof(struct v2r1_disk_dqblk)))
|
||||
m->dqb_itime = 0;
|
||||
}
|
||||
|
||||
static void v2r1_mem2diskdqb(void *dp, struct dquot *dquot)
|
||||
{
|
||||
struct v2r1_disk_dqblk *d = dp;
|
||||
struct mem_dqblk *m = &dquot->dq_dqb;
|
||||
struct qtree_mem_dqinfo *info =
|
||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||
|
||||
d->dqb_ihardlimit = cpu_to_le64(m->dqb_ihardlimit);
|
||||
d->dqb_isoftlimit = cpu_to_le64(m->dqb_isoftlimit);
|
||||
d->dqb_curinodes = cpu_to_le64(m->dqb_curinodes);
|
||||
d->dqb_itime = cpu_to_le64(m->dqb_itime);
|
||||
d->dqb_bhardlimit = cpu_to_le64(v2_stoqb(m->dqb_bhardlimit));
|
||||
d->dqb_bsoftlimit = cpu_to_le64(v2_stoqb(m->dqb_bsoftlimit));
|
||||
d->dqb_curspace = cpu_to_le64(m->dqb_curspace);
|
||||
d->dqb_btime = cpu_to_le64(m->dqb_btime);
|
||||
d->dqb_id = cpu_to_le32(dquot->dq_id);
|
||||
if (qtree_entry_unused(info, dp))
|
||||
d->dqb_itime = cpu_to_le64(1);
|
||||
}
|
||||
|
||||
static int v2r1_is_id(void *dp, struct dquot *dquot)
|
||||
{
|
||||
struct v2r1_disk_dqblk *d = dp;
|
||||
struct qtree_mem_dqinfo *info =
|
||||
sb_dqinfo(dquot->dq_sb, dquot->dq_type)->dqi_priv;
|
||||
|
||||
|
@ -207,7 +294,7 @@ static int v2_free_file_info(struct super_block *sb, int type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct quota_format_ops v2_format_ops = {
|
||||
static const struct quota_format_ops v2_format_ops = {
|
||||
.check_quota_file = v2_check_quota_file,
|
||||
.read_file_info = v2_read_file_info,
|
||||
.write_file_info = v2_write_file_info,
|
||||
|
@ -217,20 +304,32 @@ static struct quota_format_ops v2_format_ops = {
|
|||
.release_dqblk = v2_release_dquot,
|
||||
};
|
||||
|
||||
static struct quota_format_type v2_quota_format = {
|
||||
static struct quota_format_type v2r0_quota_format = {
|
||||
.qf_fmt_id = QFMT_VFS_V0,
|
||||
.qf_ops = &v2_format_ops,
|
||||
.qf_owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static struct quota_format_type v2r1_quota_format = {
|
||||
.qf_fmt_id = QFMT_VFS_V1,
|
||||
.qf_ops = &v2_format_ops,
|
||||
.qf_owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init init_v2_quota_format(void)
|
||||
{
|
||||
return register_quota_format(&v2_quota_format);
|
||||
int ret;
|
||||
|
||||
ret = register_quota_format(&v2r0_quota_format);
|
||||
if (ret)
|
||||
return ret;
|
||||
return register_quota_format(&v2r1_quota_format);
|
||||
}
|
||||
|
||||
static void __exit exit_v2_quota_format(void)
|
||||
{
|
||||
unregister_quota_format(&v2_quota_format);
|
||||
unregister_quota_format(&v2r0_quota_format);
|
||||
unregister_quota_format(&v2r1_quota_format);
|
||||
}
|
||||
|
||||
module_init(init_v2_quota_format);
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
}
|
||||
|
||||
#define V2_INITQVERSIONS {\
|
||||
0, /* USRQUOTA */\
|
||||
0 /* GRPQUOTA */\
|
||||
1, /* USRQUOTA */\
|
||||
1 /* GRPQUOTA */\
|
||||
}
|
||||
|
||||
/* First generic header */
|
||||
|
@ -32,7 +32,7 @@ struct v2_disk_dqheader {
|
|||
* (as it appears on disk) - the file is a radix tree whose leaves point
|
||||
* to blocks of these structures.
|
||||
*/
|
||||
struct v2_disk_dqblk {
|
||||
struct v2r0_disk_dqblk {
|
||||
__le32 dqb_id; /* id this quota applies to */
|
||||
__le32 dqb_ihardlimit; /* absolute limit on allocated inodes */
|
||||
__le32 dqb_isoftlimit; /* preferred inode limit */
|
||||
|
@ -44,6 +44,19 @@ struct v2_disk_dqblk {
|
|||
__le64 dqb_itime; /* time limit for excessive inode use */
|
||||
};
|
||||
|
||||
struct v2r1_disk_dqblk {
|
||||
__le32 dqb_id; /* id this quota applies to */
|
||||
__le32 dqb_pad;
|
||||
__le64 dqb_ihardlimit; /* absolute limit on allocated inodes */
|
||||
__le64 dqb_isoftlimit; /* preferred inode limit */
|
||||
__le64 dqb_curinodes; /* current # allocated inodes */
|
||||
__le64 dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
|
||||
__le64 dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
|
||||
__le64 dqb_curspace; /* current space occupied (in bytes) */
|
||||
__le64 dqb_btime; /* time limit for excessive disk use */
|
||||
__le64 dqb_itime; /* time limit for excessive inode use */
|
||||
};
|
||||
|
||||
/* Header with type and version specific information */
|
||||
struct v2_disk_dqinfo {
|
||||
__le32 dqi_bgrace; /* Time before block soft limit becomes hard limit */
|
||||
|
|
13
fs/sync.c
13
fs/sync.c
|
@ -295,10 +295,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
|
|||
*/
|
||||
int generic_write_sync(struct file *file, loff_t pos, loff_t count)
|
||||
{
|
||||
if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host))
|
||||
if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
|
||||
return 0;
|
||||
return vfs_fsync_range(file, file->f_path.dentry, pos,
|
||||
pos + count - 1, 1);
|
||||
pos + count - 1,
|
||||
(file->f_flags & __O_SYNC) ? 0 : 1);
|
||||
}
|
||||
EXPORT_SYMBOL(generic_write_sync);
|
||||
|
||||
|
@ -452,9 +453,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
|
|||
|
||||
ret = 0;
|
||||
if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
|
||||
ret = wait_on_page_writeback_range(mapping,
|
||||
offset >> PAGE_CACHE_SHIFT,
|
||||
endbyte >> PAGE_CACHE_SHIFT);
|
||||
ret = filemap_fdatawait_range(mapping, offset, endbyte);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
@ -467,9 +466,7 @@ int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
|
|||
}
|
||||
|
||||
if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
|
||||
ret = wait_on_page_writeback_range(mapping,
|
||||
offset >> PAGE_CACHE_SHIFT,
|
||||
endbyte >> PAGE_CACHE_SHIFT);
|
||||
ret = filemap_fdatawait_range(mapping, offset, endbyte);
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
|
|
|
@ -806,7 +806,7 @@ write_retry:
|
|||
XFS_STATS_ADD(xs_write_bytes, ret);
|
||||
|
||||
/* Handle various SYNC-type writes */
|
||||
if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) {
|
||||
if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
|
||||
loff_t end = pos + ret - 1;
|
||||
int error2;
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
|
||||
located on an ext2 file system */
|
||||
#define O_ACCMODE 00000003
|
||||
#define O_RDONLY 00000000
|
||||
#define O_WRONLY 00000001
|
||||
|
@ -27,8 +25,8 @@
|
|||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 00004000
|
||||
#endif
|
||||
#ifndef O_SYNC
|
||||
#define O_SYNC 00010000
|
||||
#ifndef O_DSYNC
|
||||
#define O_DSYNC 00010000 /* used to be O_SYNC, see below */
|
||||
#endif
|
||||
#ifndef FASYNC
|
||||
#define FASYNC 00020000 /* fcntl, for BSD compatibility */
|
||||
|
@ -51,6 +49,25 @@
|
|||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 02000000 /* set close_on_exec */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Before Linux 2.6.32 only O_DSYNC semantics were implemented, but using
|
||||
* the O_SYNC flag. We continue to use the existing numerical value
|
||||
* for O_DSYNC semantics now, but using the correct symbolic name for it.
|
||||
* This new value is used to request true Posix O_SYNC semantics. It is
|
||||
* defined in this strange way to make sure applications compiled against
|
||||
* new headers get at least O_DSYNC semantics on older kernels.
|
||||
*
|
||||
* This has the nice side-effect that we can simply test for O_DSYNC
|
||||
* wherever we do not care if O_DSYNC or O_SYNC is used.
|
||||
*
|
||||
* Note: __O_SYNC must never be used directly.
|
||||
*/
|
||||
#ifndef O_SYNC
|
||||
#define __O_SYNC 04000000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
#endif
|
||||
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY O_NONBLOCK
|
||||
#endif
|
||||
|
|
|
@ -565,14 +565,14 @@ struct ext2_dir_entry_2 {
|
|||
* other bits are reserved for now.
|
||||
*/
|
||||
enum {
|
||||
EXT2_FT_UNKNOWN,
|
||||
EXT2_FT_REG_FILE,
|
||||
EXT2_FT_DIR,
|
||||
EXT2_FT_CHRDEV,
|
||||
EXT2_FT_BLKDEV,
|
||||
EXT2_FT_FIFO,
|
||||
EXT2_FT_SOCK,
|
||||
EXT2_FT_SYMLINK,
|
||||
EXT2_FT_UNKNOWN = 0,
|
||||
EXT2_FT_REG_FILE = 1,
|
||||
EXT2_FT_DIR = 2,
|
||||
EXT2_FT_CHRDEV = 3,
|
||||
EXT2_FT_BLKDEV = 4,
|
||||
EXT2_FT_FIFO = 5,
|
||||
EXT2_FT_SOCK = 6,
|
||||
EXT2_FT_SYMLINK = 7,
|
||||
EXT2_FT_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -918,6 +918,8 @@ extern void ext3_abort (struct super_block *, const char *, const char *, ...)
|
|||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext3_warning (struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext3_msg(struct super_block *, const char *, const char *, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
extern void ext3_update_dynamic_rev (struct super_block *sb);
|
||||
|
||||
#define ext3_std_error(sb, errno) \
|
||||
|
|
|
@ -2091,8 +2091,6 @@ extern int filemap_fdatawait_range(struct address_space *, loff_t lstart,
|
|||
extern int filemap_write_and_wait(struct address_space *mapping);
|
||||
extern int filemap_write_and_wait_range(struct address_space *mapping,
|
||||
loff_t lstart, loff_t lend);
|
||||
extern int wait_on_page_writeback_range(struct address_space *mapping,
|
||||
pgoff_t start, pgoff_t end);
|
||||
extern int __filemap_fdatawrite_range(struct address_space *mapping,
|
||||
loff_t start, loff_t end, int sync_mode);
|
||||
extern int filemap_fdatawrite_range(struct address_space *mapping,
|
||||
|
|
|
@ -73,6 +73,8 @@
|
|||
/* Quota format type IDs */
|
||||
#define QFMT_VFS_OLD 1
|
||||
#define QFMT_VFS_V0 2
|
||||
#define QFMT_OCFS2 3
|
||||
#define QFMT_VFS_V1 4
|
||||
|
||||
/* Size of block in which space limits are passed through the quota
|
||||
* interface */
|
||||
|
@ -334,7 +336,7 @@ struct quotactl_ops {
|
|||
|
||||
struct quota_format_type {
|
||||
int qf_fmt_id; /* Quota format id */
|
||||
struct quota_format_ops *qf_ops; /* Operations of format */
|
||||
const struct quota_format_ops *qf_ops; /* Operations of format */
|
||||
struct module *qf_owner; /* Module implementing quota format */
|
||||
struct quota_format_type *qf_next;
|
||||
};
|
||||
|
@ -394,7 +396,7 @@ struct quota_info {
|
|||
struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */
|
||||
struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */
|
||||
struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
|
||||
struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
|
||||
const struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */
|
||||
};
|
||||
|
||||
int register_quota_format(struct quota_format_type *fmt);
|
||||
|
|
49
mm/filemap.c
49
mm/filemap.c
|
@ -260,27 +260,27 @@ int filemap_flush(struct address_space *mapping)
|
|||
EXPORT_SYMBOL(filemap_flush);
|
||||
|
||||
/**
|
||||
* wait_on_page_writeback_range - wait for writeback to complete
|
||||
* @mapping: target address_space
|
||||
* @start: beginning page index
|
||||
* @end: ending page index
|
||||
* filemap_fdatawait_range - wait for writeback to complete
|
||||
* @mapping: address space structure to wait for
|
||||
* @start_byte: offset in bytes where the range starts
|
||||
* @end_byte: offset in bytes where the range ends (inclusive)
|
||||
*
|
||||
* Wait for writeback to complete against pages indexed by start->end
|
||||
* inclusive
|
||||
* Walk the list of under-writeback pages of the given address space
|
||||
* in the given range and wait for all of them.
|
||||
*/
|
||||
int wait_on_page_writeback_range(struct address_space *mapping,
|
||||
pgoff_t start, pgoff_t end)
|
||||
int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
|
||||
loff_t end_byte)
|
||||
{
|
||||
pgoff_t index = start_byte >> PAGE_CACHE_SHIFT;
|
||||
pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
|
||||
struct pagevec pvec;
|
||||
int nr_pages;
|
||||
int ret = 0;
|
||||
pgoff_t index;
|
||||
|
||||
if (end < start)
|
||||
if (end_byte < start_byte)
|
||||
return 0;
|
||||
|
||||
pagevec_init(&pvec, 0);
|
||||
index = start;
|
||||
while ((index <= end) &&
|
||||
(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
|
||||
PAGECACHE_TAG_WRITEBACK,
|
||||
|
@ -310,25 +310,6 @@ int wait_on_page_writeback_range(struct address_space *mapping,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* filemap_fdatawait_range - wait for all under-writeback pages to complete in a given range
|
||||
* @mapping: address space structure to wait for
|
||||
* @start: offset in bytes where the range starts
|
||||
* @end: offset in bytes where the range ends (inclusive)
|
||||
*
|
||||
* Walk the list of under-writeback pages of the given address space
|
||||
* in the given range and wait for all of them.
|
||||
*
|
||||
* This is just a simple wrapper so that callers don't have to convert offsets
|
||||
* to page indexes themselves
|
||||
*/
|
||||
int filemap_fdatawait_range(struct address_space *mapping, loff_t start,
|
||||
loff_t end)
|
||||
{
|
||||
return wait_on_page_writeback_range(mapping, start >> PAGE_CACHE_SHIFT,
|
||||
end >> PAGE_CACHE_SHIFT);
|
||||
}
|
||||
EXPORT_SYMBOL(filemap_fdatawait_range);
|
||||
|
||||
/**
|
||||
|
@ -345,8 +326,7 @@ int filemap_fdatawait(struct address_space *mapping)
|
|||
if (i_size == 0)
|
||||
return 0;
|
||||
|
||||
return wait_on_page_writeback_range(mapping, 0,
|
||||
(i_size - 1) >> PAGE_CACHE_SHIFT);
|
||||
return filemap_fdatawait_range(mapping, 0, i_size - 1);
|
||||
}
|
||||
EXPORT_SYMBOL(filemap_fdatawait);
|
||||
|
||||
|
@ -393,9 +373,8 @@ int filemap_write_and_wait_range(struct address_space *mapping,
|
|||
WB_SYNC_ALL);
|
||||
/* See comment of filemap_write_and_wait() */
|
||||
if (err != -EIO) {
|
||||
int err2 = wait_on_page_writeback_range(mapping,
|
||||
lstart >> PAGE_CACHE_SHIFT,
|
||||
lend >> PAGE_CACHE_SHIFT);
|
||||
int err2 = filemap_fdatawait_range(mapping,
|
||||
lstart, lend);
|
||||
if (!err)
|
||||
err = err2;
|
||||
}
|
||||
|
|
|
@ -1257,7 +1257,7 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
|
|||
break;
|
||||
count -= count1;
|
||||
}
|
||||
if (file->f_flags & O_SYNC) {
|
||||
if (file->f_flags & O_DSYNC) {
|
||||
spin_lock_irq(&runtime->lock);
|
||||
while (runtime->avail != runtime->buffer_size) {
|
||||
wait_queue_t wait;
|
||||
|
|
Loading…
Reference in New Issue