Merge branch 'maint' into next

pu
Theodore Ts'o 2013-10-14 09:57:23 -04:00
commit 1586850bcd
15 changed files with 471 additions and 19 deletions

11
configure vendored
View File

@ -715,6 +715,7 @@ DEPSTATIC_LIBQUOTA
STATIC_LIBQUOTA
DEPLIBQUOTA
LIBQUOTA
QUOTA_MAN_COMMENT
BLKID_CMT
DEPPROFILED_LIBBLKID
PROFILED_LIBBLKID
@ -5191,6 +5192,9 @@ fi
QUOTA_MAN_COMMENT='.\"'
QUOTA_CMT=
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
@ -5312,17 +5316,22 @@ fi
if test "${enable_quota+set}" = set; then :
enableval=$enable_quota; if test "$enableval" = "no"
then
QUOTA_CMT=#
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling quota support" >&5
$as_echo "Disabling quota support" >&6; }
else
QUOTA_CMT=
$as_echo "#define CONFIG_QUOTA 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Enabling quota support" >&5
$as_echo "Enabling quota support" >&6; }
QUOTA_MAN_COMMENT=""
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling quota support by default" >&5
QUOTA_CMT=#
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Disabling quota support by default" >&5
$as_echo "Disabling quota support by default" >&6; }
fi

View File

@ -565,18 +565,26 @@ AC_SUBST(BLKID_CMT)
dnl
dnl handle --enable-quota
dnl
QUOTA_MAN_COMMENT='.\"'
QUOTA_CMT=
AC_SUBST(QUOTA_MAN_COMMENT)
PKG_PROG_PKG_CONFIG
AH_TEMPLATE([CONFIG_QUOTA], [Define to 1 to enable quota support])
AC_ARG_ENABLE([quota],
[ --enable-quota enable quota support],
if test "$enableval" = "no"
then
QUOTA_CMT=#
AC_MSG_RESULT([Disabling quota support])
else
QUOTA_CMT=
AC_DEFINE(CONFIG_QUOTA, 1)
AC_MSG_RESULT([Enabling quota support])
QUOTA_MAN_COMMENT=""
AC_SUBST(QUOTA_MAN_COMMENT)
fi
,
QUOTA_CMT=#
AC_MSG_RESULT([Disabling quota support by default])
)
dnl

105
contrib/populate-extfs.sh Executable file
View File

@ -0,0 +1,105 @@
#!/bin/sh
#
# This script uses debugfs command to populate the ext2/3/4 filesystem
# from a given directory.
#
do_usage () {
cat << _EOF
Usage: populate-extfs.sh <source> <device>
Create an ext2/ext3/ext4 filesystem from a directory or file
source: The source directory or file
device: The target device
_EOF
exit 1
}
[ $# -ne 2 ] && do_usage
SRCDIR=${1%%/}
DEVICE=$2
# Find where is the debugfs command if not found in the env.
if [ -z "$DEBUGFS" ]; then
CONTRIB_DIR=$(dirname $(readlink -f $0))
DEBUGFS="$CONTRIB_DIR/../debugfs/debugfs"
fi
{
CWD="/"
find $SRCDIR | while read FILE; do
TGT="${FILE##*/}"
DIR="${FILE#$SRCDIR}"
DIR="${DIR%$TGT}"
# Skip the root dir
[ ! -z "$DIR" ] || continue
[ ! -z "$TGT" ] || continue
if [ "$DIR" != "$CWD" ]; then
echo "cd $DIR"
CWD="$DIR"
fi
# Only stat once since stat is a time consuming command
STAT=$(stat -c "TYPE=\"%F\";DEVNO=\"0x%t 0x%T\";MODE=\"%f\";U=\"%u\";G=\"%g\"" $FILE)
eval $STAT
case $TYPE in
"directory")
echo "mkdir $TGT"
;;
"regular file" | "regular empty file")
echo "write $FILE $TGT"
;;
"symbolic link")
LINK_TGT=$(readlink $FILE)
echo "symlink $TGT $LINK_TGT"
;;
"block special file")
echo "mknod $TGT b $DEVNO"
;;
"character special file")
echo "mknod $TGT c $DEVNO"
;;
"fifo")
echo "mknod $TGT p"
;;
*)
echo "Unknown/unhandled file type '$TYPE' file: $FILE" 1>&2
;;
esac
# Set the file mode
echo "sif $TGT mode 0x$MODE"
# Set uid and gid
echo "sif $TGT uid $U"
echo "sif $TGT gid $G"
done
# Handle the hard links.
# Save the hard links to a file, use the inode number as the filename, for example:
# If a and b's inode number is 6775928, save a and b to /tmp/tmp.VrCwHh5gdt/6775928.
INODE_DIR=`mktemp -d` || exit 1
for i in `find $SRCDIR -type f -links +1 -printf 'INODE=%i###FN=%p\n'`; do
eval `echo $i | sed 's$###$ $'`
echo ${FN#$SRCDIR} >>$INODE_DIR/$INODE
done
# Use the debugfs' ln and "sif links_count" to handle them.
for i in `ls $INODE_DIR`; do
# The link source
SRC=`head -1 $INODE_DIR/$i`
# Remove the files and link them again except the first one
for TGT in `sed -n -e '1!p' $INODE_DIR/$i`; do
echo "rm $TGT"
echo "ln $SRC $TGT"
done
LN_CNT=`cat $INODE_DIR/$i | wc -l`
# Set the links count
echo "sif $SRC links_count $LN_CNT"
done
rm -fr $INODE_DIR
} | $DEBUGFS -w -f - $DEVICE

View File

@ -37,6 +37,20 @@ extern char *optarg;
#include "../version.h"
#include "jfs_user.h"
#ifndef BUFSIZ
#define BUFSIZ 8192
#endif
/* 64KiB is the minimium blksize to best minimize system call overhead. */
#ifndef IO_BUFSIZE
#define IO_BUFSIZE 64*1024
#endif
/* Block size for `st_blocks' */
#ifndef S_BLKSIZE
#define S_BLKSIZE 512
#endif
ss_request_table *extra_cmds;
const char *debug_prog_name;
int sci_idx;
@ -1571,22 +1585,37 @@ void do_find_free_inode(int argc, char *argv[])
}
#ifndef READ_ONLY
static errcode_t copy_file(int fd, ext2_ino_t newfile)
static errcode_t copy_file(int fd, ext2_ino_t newfile, int bufsize, int make_holes)
{
ext2_file_t e2_file;
errcode_t retval;
int got;
unsigned int written;
char buf[8192];
char *buf;
char *ptr;
char *zero_buf;
int cmp;
retval = ext2fs_file_open(current_fs, newfile,
EXT2_FILE_WRITE, &e2_file);
if (retval)
return retval;
if (!(buf = (char *) malloc(bufsize))){
com_err("copy_file", errno, "can't allocate buffer\n");
return;
}
/* This is used for checking whether the whole block is zero */
retval = ext2fs_get_memzero(bufsize, &zero_buf);
if (retval) {
com_err("copy_file", retval, "can't allocate buffer\n");
free(buf);
return retval;
}
while (1) {
got = read(fd, buf, sizeof(buf));
got = read(fd, buf, bufsize);
if (got == 0)
break;
if (got < 0) {
@ -1594,6 +1623,21 @@ static errcode_t copy_file(int fd, ext2_ino_t newfile)
goto fail;
}
ptr = buf;
/* Sparse copy */
if (make_holes) {
/* Check whether all is zero */
cmp = memcmp(ptr, zero_buf, got);
if (cmp == 0) {
/* The whole block is zero, make a hole */
retval = ext2fs_file_lseek(e2_file, got, EXT2_SEEK_CUR, NULL);
if (retval)
goto fail;
got = 0;
}
}
/* Normal copy */
while (got > 0) {
retval = ext2fs_file_write(e2_file, ptr,
got, &written);
@ -1604,10 +1648,14 @@ static errcode_t copy_file(int fd, ext2_ino_t newfile)
ptr += written;
}
}
free(buf);
ext2fs_free_mem(&zero_buf);
retval = ext2fs_file_close(e2_file);
return retval;
fail:
free(buf);
ext2fs_free_mem(&zero_buf);
(void) ext2fs_file_close(e2_file);
return retval;
}
@ -1620,6 +1668,8 @@ void do_write(int argc, char *argv[])
ext2_ino_t newfile;
errcode_t retval;
struct ext2_inode inode;
int bufsize = IO_BUFSIZE;
int make_holes = 0;
if (common_args_process(argc, argv, 3, 3, "write",
"<native file> <new file>", CHECK_FS_RW))
@ -1695,7 +1745,15 @@ void do_write(int argc, char *argv[])
return;
}
if (LINUX_S_ISREG(inode.i_mode)) {
retval = copy_file(fd, newfile);
if (statbuf.st_blocks < statbuf.st_size / S_BLKSIZE) {
make_holes = 1;
/*
* Use I/O blocksize as buffer size when
* copying sparse files.
*/
bufsize = statbuf.st_blksize;
}
retval = copy_file(fd, newfile, bufsize, make_holes);
if (retval)
com_err("copy_file", retval, 0);
}
@ -2311,7 +2369,7 @@ void do_dump_mmp(int argc EXT2FS_ATTR((unused)), char *argv[])
static int source_file(const char *cmd_file, int ss_idx)
{
FILE *f;
char buf[256];
char buf[BUFSIZ];
char *cp;
int exit_status = 0;
int retval;

View File

@ -99,6 +99,7 @@ errcode_t quota_remove_inode(ext2_filsys fs, int qtype)
quota_inode_truncate(fs, qf_ino);
ext2fs_mark_super_dirty(fs);
fs->flags &= ~EXT2_FLAG_SUPER_ONLY;
ext2fs_write_bitmaps(fs);
return 0;
}

View File

@ -291,13 +291,13 @@ as default.
.TP
.BI nodiscard
Do not attempt to discard blocks at mkfs time.
.TP
.BI quotatype
Specify which quota type ('usr' or 'grp') is to be initialized. This
option has any effect only if
.B quota
feature is set. Without this extended option, the default behavior is to
initialize both user and group quotas.
@QUOTA_MAN_COMMENT@.TP
@QUOTA_MAN_COMMENT@.BI quotatype
@QUOTA_MAN_COMMENT@Specify which quota type ('usr' or 'grp') is to be initialized. This
@QUOTA_MAN_COMMENT@option has any effect only if
@QUOTA_MAN_COMMENT@.B quota
@QUOTA_MAN_COMMENT@feature is set. Without this extended option, the default behavior is to
@QUOTA_MAN_COMMENT@initialize both user and group quotas.
.RE
.TP
.BI \-f " fragment-size"
@ -590,11 +590,11 @@ option).
.B large_file
Filesystem can contain files that are greater than 2GB. (Modern kernels
set this feature automatically when a file > 2GB is created.)
.TP
.B quota
Create quota inodes (inode# 3 for userquota and inode# 4 for group quota) and
set them in the superblock. With this feature, the quotas will be enabled
automatically when the filesystem is mounted.
@QUOTA_MAN_COMMENT@.TP
@QUOTA_MAN_COMMENT@.B quota
@QUOTA_MAN_COMMENT@Create quota inodes (inode# 3 for userquota and inode# 4 for group quota) and
@QUOTA_MAN_COMMENT@set them in the superblock. With this feature, the quotas will be enabled
@QUOTA_MAN_COMMENT@automatically when the filesystem is mounted.
.TP
.B resize_inode
Reserve space so the block group descriptor table may grow in the future.

View File

@ -124,6 +124,9 @@ static void usage(void)
"\t[-r reserved_blocks_count] [-u user] [-C mount_count] "
"[-L volume_label]\n"
"\t[-M last_mounted_dir] [-O [^]feature[,...]]\n"
#ifdef CONFIG_QUOTA
"\t[-Q quota_options]\n"
#endif
"\t[-E extended-option[,...]] [-T last_check_time] "
"[-U UUID]\n\t[ -I new_inode_size ] device\n"), program_name);
exit(1);
@ -1366,11 +1369,15 @@ static void parse_tune2fs_options(int argc, char **argv)
char *tmp;
struct group *gr;
struct passwd *pw;
char optstring[100] = "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:T:U:";
#ifdef CONFIG_QUOTA
strcat(optstring, "Q:");
#endif
open_flag = 0;
printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:E:I:J:L:M:O:Q:T:U:")) != EOF)
while ((c = getopt(argc, argv, optstring)) != EOF)
switch (c) {
case 'c':
max_mount_count = strtol(optarg, &tmp, 0);
@ -1524,11 +1531,13 @@ static void parse_tune2fs_options(int argc, char **argv)
features_cmd = optarg;
open_flag = EXT2_FLAG_RW;
break;
#ifdef CONFIG_QUOTA
case 'Q':
Q_flag = 1;
parse_quota_opts(optarg);
open_flag = EXT2_FLAG_RW;
break;
#endif
case 'r':
reserved_blocks = strtoul(optarg, &tmp, 0);
if (*tmp) {

View File

@ -17,6 +17,7 @@ test_one: $(srcdir)/test_one.in Makefile mke2fs.conf
@echo "Creating test_one script..."
@echo "#!/bin/sh" > test_one
@HTREE_CMT@ @echo "HTREE=y" >> test_one
@QUOTA_CMT@ @echo "QUOTA=y" >> test_one
@echo "SRCDIR=@srcdir@" >> test_one
@echo "DIFF_OPTS=@UNI_DIFF_OPTS@" >> test_one
@cat $(srcdir)/test_one.in >> test_one

172
tests/m_quota/expect.1 Normal file
View File

@ -0,0 +1,172 @@
Warning: the quota feature is still under development
See https://ext4.wiki.kernel.org/index.php/Quota for more information
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
32768 inodes, 131072 blocks
6553 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
16 block groups
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super quota
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
test_filesys: 11/32768 files (18.2% non-contiguous), 5703/131072 blocks
Exit status is 0
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: ext_attr resize_inode dir_index filetype sparse_super quota
Default mount options: (none)
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 32768
Block count: 131072
Reserved block count: 6553
Free blocks: 125369
Free inodes: 32757
First block: 1
Block size: 1024
Fragment size: 1024
Reserved GDT blocks: 256
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 2048
Inode blocks per group: 256
Mount count: 0
Check interval: 15552000 (6 months)
Reserved blocks uid: 0
Reserved blocks gid: 0
First inode: 11
Inode size: 128
Default directory hash: half_md4
User quota inode: 3
Group quota inode: 4
Group 0: (Blocks 1-8192)
Primary superblock at 1, Group descriptors at 2-2
Reserved GDT blocks at 3-258
Block bitmap at 259 (+258), Inode bitmap at 260 (+259)
Inode table at 261-516 (+260)
7650 free blocks, 2037 free inodes, 2 directories
Free blocks: 543-8192
Free inodes: 12-2048
Group 1: (Blocks 8193-16384)
Backup superblock at 8193, Group descriptors at 8194-8194
Reserved GDT blocks at 8195-8450
Block bitmap at 8451 (+258), Inode bitmap at 8452 (+259)
Inode table at 8453-8708 (+260)
7676 free blocks, 2048 free inodes, 0 directories
Free blocks: 8709-16384
Free inodes: 2049-4096
Group 2: (Blocks 16385-24576)
Block bitmap at 16385 (+0), Inode bitmap at 16386 (+1)
Inode table at 16387-16642 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 16643-24576
Free inodes: 4097-6144
Group 3: (Blocks 24577-32768)
Backup superblock at 24577, Group descriptors at 24578-24578
Reserved GDT blocks at 24579-24834
Block bitmap at 24835 (+258), Inode bitmap at 24836 (+259)
Inode table at 24837-25092 (+260)
7676 free blocks, 2048 free inodes, 0 directories
Free blocks: 25093-32768
Free inodes: 6145-8192
Group 4: (Blocks 32769-40960)
Block bitmap at 32769 (+0), Inode bitmap at 32770 (+1)
Inode table at 32771-33026 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 33027-40960
Free inodes: 8193-10240
Group 5: (Blocks 40961-49152)
Backup superblock at 40961, Group descriptors at 40962-40962
Reserved GDT blocks at 40963-41218
Block bitmap at 41219 (+258), Inode bitmap at 41220 (+259)
Inode table at 41221-41476 (+260)
7676 free blocks, 2048 free inodes, 0 directories
Free blocks: 41477-49152
Free inodes: 10241-12288
Group 6: (Blocks 49153-57344)
Block bitmap at 49153 (+0), Inode bitmap at 49154 (+1)
Inode table at 49155-49410 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 49411-57344
Free inodes: 12289-14336
Group 7: (Blocks 57345-65536)
Backup superblock at 57345, Group descriptors at 57346-57346
Reserved GDT blocks at 57347-57602
Block bitmap at 57603 (+258), Inode bitmap at 57604 (+259)
Inode table at 57605-57860 (+260)
7676 free blocks, 2048 free inodes, 0 directories
Free blocks: 57861-65536
Free inodes: 14337-16384
Group 8: (Blocks 65537-73728)
Block bitmap at 65537 (+0), Inode bitmap at 65538 (+1)
Inode table at 65539-65794 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 65795-73728
Free inodes: 16385-18432
Group 9: (Blocks 73729-81920)
Backup superblock at 73729, Group descriptors at 73730-73730
Reserved GDT blocks at 73731-73986
Block bitmap at 73987 (+258), Inode bitmap at 73988 (+259)
Inode table at 73989-74244 (+260)
7676 free blocks, 2048 free inodes, 0 directories
Free blocks: 74245-81920
Free inodes: 18433-20480
Group 10: (Blocks 81921-90112)
Block bitmap at 81921 (+0), Inode bitmap at 81922 (+1)
Inode table at 81923-82178 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 82179-90112
Free inodes: 20481-22528
Group 11: (Blocks 90113-98304)
Block bitmap at 90113 (+0), Inode bitmap at 90114 (+1)
Inode table at 90115-90370 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 90371-98304
Free inodes: 22529-24576
Group 12: (Blocks 98305-106496)
Block bitmap at 98305 (+0), Inode bitmap at 98306 (+1)
Inode table at 98307-98562 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 98563-106496
Free inodes: 24577-26624
Group 13: (Blocks 106497-114688)
Block bitmap at 106497 (+0), Inode bitmap at 106498 (+1)
Inode table at 106499-106754 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 106755-114688
Free inodes: 26625-28672
Group 14: (Blocks 114689-122880)
Block bitmap at 114689 (+0), Inode bitmap at 114690 (+1)
Inode table at 114691-114946 (+2)
7934 free blocks, 2048 free inodes, 0 directories
Free blocks: 114947-122880
Free inodes: 28673-30720
Group 15: (Blocks 122881-131071)
Block bitmap at 122881 (+0), Inode bitmap at 122882 (+1)
Inode table at 122883-123138 (+2)
7933 free blocks, 2048 free inodes, 0 directories
Free blocks: 123139-131071
Free inodes: 30721-32768

8
tests/m_quota/script Normal file
View File

@ -0,0 +1,8 @@
DESCRIPTION="enable quota feature on mkfs"
FS_SIZE=131072
MKE2FS_OPTS="-O quota"
if [ "$QUOTA" != "y" ]; then
echo "$test_name: $DESCRIPTION: skipped"
return 0
fi
. $cmd_dir/run_mke2fs

1
tests/t_quota_1on/name Normal file
View File

@ -0,0 +1 @@
enable quota using tune2fs

42
tests/t_quota_1on/script Normal file
View File

@ -0,0 +1,42 @@
FSCK_OPT=-yf
if [ "$QUOTA" != "y" ]; then
echo "$test_name: $test_description: skipped"
return 0
fi
$MKE2FS -q -F -o Linux -b 4096 $TMPFILE 10000 > $test_name.log 2>&1
status=$?
if [ "$status" != 0 ] ; then
echo "mke2fs failed" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
dd if=/dev/zero of=$TMPFILE.2 bs=1048576 count=1 >> $test_name.log 2>&1
cat <<- EOF | $DEBUGFS -w -f /dev/stdin $TMPFILE >> $test_name.log 2>&1
write $TMPFILE.2 file1
set_inode_field file1 uid 500
set_inode_field file1 gid 500
EOF
rm -f $TMPFILE.2
$TUNE2FS -O quota $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" != 0 ] ; then
echo "tune2fs -O quota failed with $status" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
$FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" = 0 ] ; then
echo "$test_name: $test_description: ok"
touch $test_name.ok
else
echo "e2fsck with quota enabled failed with $status" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
rm -f $TMPFILE

1
tests/t_quota_2off/name Normal file
View File

@ -0,0 +1 @@
disable quota using tune2fs

35
tests/t_quota_2off/script Normal file
View File

@ -0,0 +1,35 @@
FSCK_OPT=-yf
if [ "$QUOTA" != "y" ]; then
echo "$test_name: $test_description: skipped"
return 0
fi
$MKE2FS -q -F -o Linux -b 4096 -O quota $TMPFILE 100 > $test_name.log 2>&1
status=$?
if [ "$status" != 0 ] ; then
echo "mke2fs -O quota failed" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
$TUNE2FS -O ^quota $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" != 0 ] ; then
echo "tune2fs -O ^quota failed" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
$FSCK $FSCK_OPT $TMPFILE >> $test_name.log 2>&1
status=$?
if [ "$status" = 0 ] ; then
echo "$test_name: $test_description: ok"
touch $test_name.ok
else
echo "e2fsck with quota enabled failed with $status" > $test_name.failed
echo "$test_name: $test_description: failed"
return $status
fi
rm -f $TMPFILE

View File

@ -18,3 +18,5 @@ $prefix @prefix@
# Enable the documentation for the journal device mke2fs, tune2fs, and
# e2fsck's man page
JDEV
# Enable documentation for quota feature in mke2fs
QUOTA_MAN_COMMENT @QUOTA_MAN_COMMENT@