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:
Linus Torvalds 2009-12-11 15:31:13 -08:00
commit 3126c136bc
50 changed files with 1004 additions and 711 deletions

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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) ||

View file

@ -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);

View file

@ -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 */

View file

@ -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. */

View file

@ -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
/*

View file

@ -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

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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,

View file

@ -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 *);

View file

@ -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));

View file

@ -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;
}

View file

@ -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");
}
}

View file

@ -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;
}

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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;

View file

@ -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 */

View file

@ -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",

View file

@ -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,

View file

@ -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);

View file

@ -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)

View file

@ -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;
}

View file

@ -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)

View file

@ -17,10 +17,6 @@
#include "ocfs2.h"
/* Common stuff */
/* id number of quota format */
#define QFMT_OCFS2 3
/*
* In-memory structures
*/

View file

@ -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,

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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 */

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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
};

View file

@ -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) \

View file

@ -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,

View file

@ -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);

View file

@ -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;
}

View file

@ -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;