summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/Config.in20
-rw-r--r--fs/Makefile17
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/adfs/file.c2
-rw-r--r--fs/affs/dir.c2
-rw-r--r--fs/affs/file.c4
-rw-r--r--fs/affs/symlink.c143
-rw-r--r--fs/autofs/dir.c2
-rw-r--r--fs/autofs/root.c2
-rw-r--r--fs/autofs/symlink.c44
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/bfs/dir.c2
-rw-r--r--fs/bfs/file.c2
-rw-r--r--fs/binfmt_aout.c9
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/binfmt_misc.c6
-rw-r--r--fs/buffer.c429
-rw-r--r--fs/coda/dir.c3
-rw-r--r--fs/coda/file.c17
-rw-r--r--fs/coda/pioctl.c2
-rw-r--r--fs/coda/symlink.c116
-rw-r--r--fs/coda/sysctl.c10
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/devices.c4
-rw-r--r--fs/devpts/root.c2
-rw-r--r--fs/dquot.c723
-rw-r--r--fs/efs/dir.c2
-rw-r--r--fs/efs/file.c2
-rw-r--r--fs/efs/symlink.c118
-rw-r--r--fs/exec.c3
-rw-r--r--fs/ext2/acl.c1
-rw-r--r--fs/ext2/balloc.c1
-rw-r--r--fs/ext2/bitmap.c1
-rw-r--r--fs/ext2/dir.c3
-rw-r--r--fs/ext2/file.c3
-rw-r--r--fs/ext2/fsync.c1
-rw-r--r--fs/ext2/ialloc.c3
-rw-r--r--fs/ext2/inode.c8
-rw-r--r--fs/ext2/ioctl.c1
-rw-r--r--fs/ext2/namei.c59
-rw-r--r--fs/ext2/symlink.c100
-rw-r--r--fs/ext2/truncate.c1
-rw-r--r--fs/fat/file.c30
-rw-r--r--fs/fifo.c19
-rw-r--r--fs/filesystems.c1
-rw-r--r--fs/hfs/dir_cap.c6
-rw-r--r--fs/hfs/dir_dbl.c2
-rw-r--r--fs/hfs/dir_nat.c4
-rw-r--r--fs/hfs/file.c2
-rw-r--r--fs/hfs/file_cap.c2
-rw-r--r--fs/hfs/file_hdr.c2
-rw-r--r--fs/hpfs/ea.c58
-rw-r--r--fs/hpfs/file.c48
-rw-r--r--fs/hpfs/hpfs_fn.h8
-rw-r--r--fs/hpfs/inode.c30
-rw-r--r--fs/hpfs/namei.c61
-rw-r--r--fs/inode.c49
-rw-r--r--fs/isofs/dir.c2
-rw-r--r--fs/isofs/file.c2
-rw-r--r--fs/isofs/inode.c7
-rw-r--r--fs/isofs/rock.c277
-rw-r--r--fs/isofs/symlink.c67
-rw-r--r--fs/minix/dir.c2
-rw-r--r--fs/minix/file.c2
-rw-r--r--fs/minix/namei.c57
-rw-r--r--fs/minix/symlink.c72
-rw-r--r--fs/msdos/namei.c2
-rw-r--r--fs/namei.c92
-rw-r--r--fs/ncpfs/Config.in6
-rw-r--r--fs/ncpfs/dir.c288
-rw-r--r--fs/ncpfs/file.c2
-rw-r--r--fs/ncpfs/inode.c17
-rw-r--r--fs/ncpfs/ioctl.c80
-rw-r--r--fs/ncpfs/mmap.c6
-rw-r--r--fs/ncpfs/ncplib_kernel.c222
-rw-r--r--fs/ncpfs/ncplib_kernel.h100
-rw-r--r--fs/ncpfs/symlink.c159
-rw-r--r--fs/nfs/dir.c106
-rw-r--r--fs/nfs/file.c5
-rw-r--r--fs/nfs/inode.c2
-rw-r--r--fs/nfs/read.c19
-rw-r--r--fs/nfs/symlink.c159
-rw-r--r--fs/nfs/write.c8
-rw-r--r--fs/nfsd/Makefile3
-rw-r--r--fs/nfsd/export.c20
-rw-r--r--fs/nfsd/nfs3proc.c622
-rw-r--r--fs/nfsd/nfs3xdr.c324
-rw-r--r--fs/nfsd/nfsctl.c2
-rw-r--r--fs/nfsd/nfsfh.c131
-rw-r--r--fs/nfsd/nfsproc.c53
-rw-r--r--fs/nfsd/nfssvc.c24
-rw-r--r--fs/nfsd/nfsxdr.c47
-rw-r--r--fs/nfsd/stats.c10
-rw-r--r--fs/nfsd/vfs.c520
-rw-r--r--fs/nls/nls_base.c76
-rw-r--r--fs/nls/nls_cp437.c61
-rw-r--r--fs/nls/nls_cp737.c61
-rw-r--r--fs/nls/nls_cp775.c67
-rw-r--r--fs/nls/nls_cp850.c67
-rw-r--r--fs/nls/nls_cp852.c75
-rw-r--r--fs/nls/nls_cp855.c79
-rw-r--r--fs/nls/nls_cp857.c69
-rw-r--r--fs/nls/nls_cp860.c63
-rw-r--r--fs/nls/nls_cp861.c65
-rw-r--r--fs/nls/nls_cp862.c58
-rw-r--r--fs/nls/nls_cp863.c62
-rw-r--r--fs/nls/nls_cp864.c58
-rw-r--r--fs/nls/nls_cp865.c64
-rw-r--r--fs/nls/nls_cp866.c60
-rw-r--r--fs/nls/nls_cp869.c70
-rw-r--r--fs/nls/nls_cp874.c62
-rw-r--r--fs/nls/nls_iso8859-1.c70
-rw-r--r--fs/nls/nls_iso8859-14.c75
-rw-r--r--fs/nls/nls_iso8859-15.c75
-rw-r--r--fs/nls/nls_iso8859-2.c72
-rw-r--r--fs/nls/nls_iso8859-3.c80
-rw-r--r--fs/nls/nls_iso8859-4.c74
-rw-r--r--fs/nls/nls_iso8859-5.c70
-rw-r--r--fs/nls/nls_iso8859-6.c74
-rw-r--r--fs/nls/nls_iso8859-7.c76
-rw-r--r--fs/nls/nls_iso8859-8.c74
-rw-r--r--fs/nls/nls_iso8859-9.c70
-rw-r--r--fs/nls/nls_koi8-r.c60
-rw-r--r--fs/ntfs/fs.c16
-rw-r--r--fs/ntfs/super.c8
-rw-r--r--fs/ntfs/super.h2
-rw-r--r--fs/open.c41
-rw-r--r--fs/partitions/Config.in3
-rw-r--r--fs/pipe.c70
-rw-r--r--fs/proc/Makefile2
-rw-r--r--fs/proc/array.c1
-rw-r--r--fs/proc/base.c21
-rw-r--r--fs/proc/generic.c387
-rw-r--r--fs/proc/inode-alloc.txt1
-rw-r--r--fs/proc/inode.c87
-rw-r--r--fs/proc/kcore.c74
-rw-r--r--fs/proc/kmsg.c19
-rw-r--r--fs/proc/omirr.c19
-rw-r--r--fs/proc/openprom-dev.c46
-rw-r--r--fs/proc/openpromfs.c208
-rw-r--r--fs/proc/proc_devtree.c97
-rw-r--r--fs/proc/proc_misc.c18
-rw-r--r--fs/proc/proc_tty.c20
-rw-r--r--fs/proc/procfs_syms.c12
-rw-r--r--fs/proc/root.c563
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/file.c15
-rw-r--r--fs/qnx4/inode.c14
-rw-r--r--fs/qnx4/symlinks.c2
-rw-r--r--fs/romfs/inode.c87
-rw-r--r--fs/smbfs/cache.c149
-rw-r--r--fs/smbfs/dir.c2
-rw-r--r--fs/smbfs/file.c10
-rw-r--r--fs/super.c31
-rw-r--r--fs/sysv/dir.c2
-rw-r--r--fs/sysv/file.c2
-rw-r--r--fs/sysv/inode.c1
-rw-r--r--fs/sysv/namei.c64
-rw-r--r--fs/sysv/symlink.c73
-rw-r--r--fs/sysv/truncate.c2
-rw-r--r--fs/udf/balloc.c50
-rw-r--r--fs/udf/dir.c11
-rw-r--r--fs/udf/directory.c3
-rw-r--r--fs/udf/file.c24
-rw-r--r--fs/udf/inode.c39
-rw-r--r--fs/udf/lowlevel.c2
-rw-r--r--fs/udf/namei.c50
-rw-r--r--fs/udf/super.c16
-rw-r--r--fs/udf/symlink.c184
-rw-r--r--fs/udf/truncate.c3
-rw-r--r--fs/udf/udf_sb.h3
-rw-r--r--fs/udf/udfdecl.h233
-rw-r--r--fs/udf/udfend.h5
-rw-r--r--fs/ufs/dir.c2
-rw-r--r--fs/ufs/file.c2
-rw-r--r--fs/ufs/inode.c4
-rw-r--r--fs/ufs/namei.c57
-rw-r--r--fs/ufs/symlink.c119
-rw-r--r--fs/ufs/truncate.c2
-rw-r--r--fs/umsdos/README-WIP.txt10
-rw-r--r--fs/umsdos/check.c9
-rw-r--r--fs/umsdos/dir.c8
-rw-r--r--fs/umsdos/inode.c9
-rw-r--r--fs/umsdos/ioctl.c7
-rw-r--r--fs/umsdos/namei.c62
-rw-r--r--fs/umsdos/rdir.c3
-rw-r--r--fs/umsdos/symlink.c139
-rw-r--r--fs/vfat/namei.c2
188 files changed, 5861 insertions, 5071 deletions
diff --git a/fs/Config.in b/fs/Config.in
index b15be4a0d..150e1c95b 100644
--- a/fs/Config.in
+++ b/fs/Config.in
@@ -12,17 +12,17 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'ADFS filesystem support (read only) (EXPERIMENTAL)' CONFIG_ADFS_FS
fi
tristate 'Amiga FFS filesystem support' CONFIG_AFFS_FS
-tristate 'Apple Macintosh filesystem support (EXPERIMENTAL)' CONFIG_HFS_FS
-# msdos filesystems
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'Apple Macintosh filesystem support (EXPERIMENTAL)' CONFIG_HFS_FS
tristate 'BFS filesystem (read only) support (EXPERIMENTAL)' CONFIG_BFS_FS
if [ "$CONFIG_BFS_FS" != "n" ]; then
bool ' BFS filesystem write support (DANGEROUS)' CONFIG_BFS_FS_WRITE
fi
fi
+# msdos filesystems
tristate 'DOS FAT fs support' CONFIG_FAT_FS
dep_tristate ' MSDOS fs support' CONFIG_MSDOS_FS $CONFIG_FAT_FS
-dep_tristate ' UMSDOS: Unix-like filesystem on top of standard MSDOS filesystem' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
+dep_tristate ' UMSDOS: Unix-like filesystem on top of standard MSDOS fs' CONFIG_UMSDOS_FS $CONFIG_MSDOS_FS
dep_tristate ' VFAT (Windows-95) fs support' CONFIG_VFAT_FS $CONFIG_FAT_FS
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -37,11 +37,6 @@ else
define_bool CONFIG_JOLIET n
fi
-tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS
-if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW
-fi
-
tristate 'Minix fs support' CONFIG_MINIX_FS
tristate 'NTFS filesystem support (read only)' CONFIG_NTFS_FS
if [ "$CONFIG_NTFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
@@ -68,6 +63,10 @@ tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
fi
+tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS
+if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' UDF write support (DANGEROUS)' CONFIG_UDF_RW
+fi
tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
if [ "$CONFIG_UFS_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' UFS filesystem write support (DANGEROUS)' CONFIG_UFS_FS_WRITE
@@ -87,8 +86,11 @@ if [ "$CONFIG_INET" = "y" ]; then
fi
tristate 'NFS server support' CONFIG_NFSD
if [ "$CONFIG_NFSD" != "n" ]; then
- bool ' Emulate SUN NFS server' CONFIG_NFSD_SUN
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ bool ' Provide NFSv3 server support (EXPERIMENTAL)' CONFIG_NFSD_V3
+ fi
fi
+
if [ "$CONFIG_NFS_FS" = "y" -o "$CONFIG_NFSD" = "y" ]; then
define_tristate CONFIG_SUNRPC y
define_tristate CONFIG_LOCKD y
diff --git a/fs/Makefile b/fs/Makefile
index 88810457d..6b22588cb 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -265,14 +265,6 @@ else
endif
endif
-ifeq ($(CONFIG_BINFMT_ELF),y)
-BINFMTS += binfmt_elf.o
-else
- ifeq ($(CONFIG_BINFMT_ELF),m)
- M_OBJS += binfmt_elf.o
- endif
-endif
-
ifeq ($(CONFIG_BINFMT_AOUT),y)
BINFMTS += binfmt_aout.o
else
@@ -289,7 +281,6 @@ else
endif
endif
-
ifeq ($(CONFIG_BINFMT_MISC),y)
BINFMTS += binfmt_misc.o
else
@@ -301,4 +292,12 @@ endif
# binfmt_script is always there
BINFMTS += binfmt_script.o
+ifeq ($(CONFIG_BINFMT_ELF),y)
+BINFMTS += binfmt_elf.o
+else
+ ifeq ($(CONFIG_BINFMT_ELF),m)
+ M_OBJS += binfmt_elf.o
+ endif
+endif
+
include $(TOPDIR)/Rules.make
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index 0d0d11a06..f3eb4e872 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -54,10 +54,8 @@ struct inode_operations adfs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* read page */
NULL, /* write page */
- NULL, /* flush page */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/adfs/file.c b/fs/adfs/file.c
index c415597e3..2881e81f1 100644
--- a/fs/adfs/file.c
+++ b/fs/adfs/file.c
@@ -64,9 +64,7 @@ struct inode_operations adfs_file_inode_operations = {
adfs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/affs/dir.c b/fs/affs/dir.c
index b88eac770..f126dcbb8 100644
--- a/fs/affs/dir.c
+++ b/fs/affs/dir.c
@@ -60,10 +60,8 @@ struct inode_operations affs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permissions */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/affs/file.c b/fs/affs/file.c
index 358c1c56c..e32b9c344 100644
--- a/fs/affs/file.c
+++ b/fs/affs/file.c
@@ -77,10 +77,8 @@ struct inode_operations affs_file_inode_operations = {
affs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
affs_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -118,10 +116,8 @@ struct inode_operations affs_file_inode_operations_ofs = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
affs_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/affs/symlink.c b/fs/affs/symlink.c
index 18c03730f..6aad1c222 100644
--- a/fs/affs/symlink.c
+++ b/fs/affs/symlink.c
@@ -9,103 +9,19 @@
*/
#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/affs_fs.h>
#include <linux/amigaffs.h>
-#include <asm/uaccess.h>
+#include <linux/pagemap.h>
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))
-
-static int affs_readlink(struct dentry *, char *, int);
-static struct dentry *affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int);
-
-struct inode_operations affs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- affs_readlink, /* readlink */
- affs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static int
-affs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static int affs_symlink_readpage(struct dentry *dentry, struct page *page)
{
+ struct buffer_head *bh;
struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- struct slink_front *lf;
- int i, j;
- char c;
- char lc;
- char *pf;
-
- pr_debug("AFFS: readlink(ino=%lu,buflen=%d)\n",inode->i_ino,buflen);
-
- bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
- if (!bh) {
- affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
- inode->i_ino);
- return -EIO;
- }
- lf = (struct slink_front *)bh->b_data;
- lc = 0;
- i = 0;
- j = 0;
- pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
-
- if (strchr(lf->symname,':')) { /* Handle assign or volume name */
- while (i < buflen && (c = pf[i])) {
- put_user(c,buffer++);
- i++;
- }
- while (i < buflen && (c = lf->symname[j]) != ':') {
- put_user(c,buffer++);
- i++, j++;
- }
- if (i < buflen) {
- put_user('/',buffer++);
- i++, j++;
- }
- lc = '/';
- }
- while (i < buflen && (c = lf->symname[j])) {
- if (c == '/' && lc == '/' && (i + 3 < buflen)) { /* parent dir */
- put_user('.',buffer++);
- put_user('.',buffer++);
- i += 2;
- }
- put_user(c,buffer++);
- lc = c;
- i++, j++;
- }
- affs_brelse(bh);
- return i;
-}
-
-static struct dentry *
-affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh;
- struct slink_front *lf;
- char *buffer;
+ char *link = (char*)kmap(page);
+ struct slink_front *lf;
+ int err;
int i, j;
char c;
char lc;
@@ -113,47 +29,50 @@ affs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow
pr_debug("AFFS: follow_link(ino=%lu)\n",inode->i_ino);
- if (!(buffer = kmalloc(1024,GFP_KERNEL))) {
- dput(base);
- return ERR_PTR(-ENOSPC);
- }
+ err = -EIO;
bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
- if (!bh) {
- affs_warning(inode->i_sb,"follow_link","Unable to read i-node block %lu\n",
- inode->i_ino);
- kfree(buffer);
- dput(base);
- return ERR_PTR(-EIO);
- }
+ if (!bh)
+ goto fail;
i = 0;
j = 0;
lf = (struct slink_front *)bh->b_data;
lc = 0;
pf = inode->i_sb->u.affs_sb.s_prefix ? inode->i_sb->u.affs_sb.s_prefix : "/";
- if (strchr(lf->symname,':')) { /* Handle assign or volume name */
+ if (strchr(lf->symname,':')) { /* Handle assign or volume name */
while (i < 1023 && (c = pf[i]))
- buffer[i++] = c;
+ link[i++] = c;
while (i < 1023 && lf->symname[j] != ':')
- buffer[i++] = lf->symname[j++];
+ link[i++] = lf->symname[j++];
if (i < 1023)
- buffer[i++] = '/';
+ link[i++] = '/';
j++;
lc = '/';
}
while (i < 1023 && (c = lf->symname[j])) {
if (c == '/' && lc == '/' && i < 1020) { /* parent dir */
- buffer[i++] = '.';
- buffer[i++] = '.';
+ link[i++] = '.';
+ link[i++] = '.';
}
- buffer[i++] = c;
+ link[i++] = c;
lc = c;
j++;
}
- buffer[i] = '\0';
+ link[i] = '\0';
affs_brelse(bh);
- base = lookup_dentry(buffer,base,follow);
- kfree(buffer);
- return base;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
}
+struct inode_operations affs_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: affs_symlink_readpage,
+};
diff --git a/fs/autofs/dir.c b/fs/autofs/dir.c
index a8262e701..018b6787b 100644
--- a/fs/autofs/dir.c
+++ b/fs/autofs/dir.c
@@ -76,10 +76,8 @@ struct inode_operations autofs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index c6034c754..4f0569ca7 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -57,10 +57,8 @@ struct inode_operations autofs_root_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/autofs/symlink.c b/fs/autofs/symlink.c
index 6ca720527..129d5917f 100644
--- a/fs/autofs/symlink.c
+++ b/fs/autofs/symlink.c
@@ -10,51 +10,21 @@
*
* ------------------------------------------------------------------------- */
-#include <linux/string.h>
-#include <linux/sched.h>
#include "autofs_i.h"
static int autofs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- struct autofs_symlink *sl;
- int len;
-
- sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
- len = sl->len;
- if (len > buflen) len = buflen;
- copy_to_user(buffer, sl->data, len);
- return len;
+ char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_readlink(dentry, buffer, buflen, s);
}
-static struct dentry * autofs_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
+static struct dentry *autofs_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
{
- struct autofs_symlink *sl;
-
- sl = (struct autofs_symlink *)dentry->d_inode->u.generic_ip;
- return lookup_dentry(sl->data, base, follow);
+ char *s=((struct autofs_symlink *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_follow_link(dentry, base, flags, s);
}
struct inode_operations autofs_symlink_inode_operations = {
- NULL, /* file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- autofs_readlink, /* readlink */
- autofs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: autofs_readlink,
+ follow_link: autofs_follow_link
};
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 2691953f2..4369e2a86 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -63,10 +63,8 @@ struct inode_operations bad_inode_ops =
EIO_ERROR, /* get_block */
EIO_ERROR, /* readpage */
EIO_ERROR, /* writepage */
- EIO_ERROR, /* flushpage */
EIO_ERROR, /* truncate */
EIO_ERROR, /* permission */
- EIO_ERROR, /* smap */
EIO_ERROR /* revalidate */
};
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 8aa200451..6f5c240d2 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -283,10 +283,8 @@ struct inode_operations bfs_dir_inops = {
get_block: NULL,
readpage: NULL,
writepage: NULL,
- flushpage: NULL,
truncate: NULL,
permission: NULL,
- smap: NULL,
revalidate: NULL
};
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
index 4bc1ed99a..856ed33cd 100644
--- a/fs/bfs/file.c
+++ b/fs/bfs/file.c
@@ -68,9 +68,7 @@ struct inode_operations bfs_file_inops = {
get_block: bfs_get_block,
readpage: block_read_full_page,
writepage: block_write_full_page,
- flushpage: block_flushpage,
truncate: NULL,
permission: NULL,
- smap: NULL,
revalidate: NULL
};
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index ca5d8e8cb..41138e3fd 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -27,7 +27,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
static int load_aout_binary(struct linux_binprm *, struct pt_regs * regs);
static int load_aout_library(int fd);
@@ -551,5 +551,8 @@ static void __exit exit_aout_binfmt(void)
unregister_binfmt(&aout_format);
}
-module_init(init_aout_binfmt)
-module_exit(exit_aout_binfmt)
+EXPORT_NO_SYMBOLS;
+
+module_init(init_aout_binfmt);
+module_exit(exit_aout_binfmt);
+
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 1a4d09361..470c122b2 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -31,7 +31,7 @@
#include <linux/init.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <linux/config.h>
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 358890dbd..5d5d17bc4 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -476,7 +476,7 @@ static int __init init_misc_binfmt(void)
int error = -ENOENT;
struct proc_dir_entry *status = NULL, *reg;
- bm_dir = create_proc_entry("sys/fs/binfmt_misc", S_IFDIR, NULL);
+ bm_dir = proc_mkdir("sys/fs/binfmt_misc", NULL); /* WTF??? */
if (!bm_dir)
goto out;
bm_dir->owner = THIS_MODULE;
@@ -515,5 +515,5 @@ static void __exit exit_misc_binfmt(void)
EXPORT_NO_SYMBOLS;
-module_init(init_misc_binfmt)
-module_exit(exit_misc_binfmt)
+module_init(init_misc_binfmt);
+module_exit(exit_misc_binfmt);
diff --git a/fs/buffer.c b/fs/buffer.c
index 0b1fd9c61..6bf84ca27 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1236,7 +1236,7 @@ static void unmap_buffer(struct buffer_head * bh)
* we have truncated the file and are going to free the
* blocks on-disk..
*/
-int block_flushpage(struct inode *inode, struct page *page, unsigned long offset)
+int block_flushpage(struct page *page, unsigned long offset)
{
struct buffer_head *head, *bh, *next;
unsigned int curr_off = 0;
@@ -1324,9 +1324,8 @@ static void unmap_underlying_metadata(struct buffer_head * bh)
* block_write_full_page() is SMP-safe - currently it's still
* being called with the kernel lock held, but the code is ready.
*/
-int block_write_full_page(struct file *file, struct page *page)
+int block_write_full_page(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
int err, i;
unsigned long block;
@@ -1379,24 +1378,16 @@ out:
return err;
}
-int block_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+int block_write_zero_range(struct inode *inode, struct page *page,
+ unsigned zerofrom, unsigned from, unsigned to,
+ const char * buf)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
+ unsigned zeroto = 0, block_start, block_end;
unsigned long block;
- int err, partial;
- unsigned long blocksize, start_block, end_block;
- unsigned long start_offset, start_bytes, end_bytes;
- unsigned long bbits, blocks, i, len;
- struct buffer_head *bh, *head;
- char *target_buf, *kaddr;
- int need_balance_dirty;
-
- kaddr = (char *)kmap(page);
- target_buf = kaddr + offset;
-
- if (!PageLocked(page))
- BUG();
+ int err = 0, partial = 0, need_balance_dirty = 0;
+ unsigned blocksize, bbits;
+ struct buffer_head *bh, *head, *wait[2], **wait_bh=wait;
+ char *kaddr = (char *)kmap(page);
blocksize = inode->i_sb->s_blocksize;
if (!page->buffers)
@@ -1405,49 +1396,21 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long
bbits = inode->i_sb->s_blocksize_bits;
block = page->index << (PAGE_CACHE_SHIFT - bbits);
- blocks = PAGE_CACHE_SIZE >> bbits;
- start_block = offset >> bbits;
- end_block = (offset + bytes - 1) >> bbits;
- start_offset = offset & (blocksize - 1);
- start_bytes = blocksize - start_offset;
- if (start_bytes > bytes)
- start_bytes = bytes;
- end_bytes = (offset+bytes) & (blocksize - 1);
- if (end_bytes > bytes)
- end_bytes = bytes;
-
- if (offset < 0 || offset >= PAGE_SIZE)
- BUG();
- if (bytes+offset < 0 || bytes+offset > PAGE_SIZE)
- BUG();
- if (start_block < 0 || start_block >= blocks)
- BUG();
- if (end_block < 0 || end_block >= blocks)
- BUG();
- i = 0;
- bh = head;
- partial = 0;
- need_balance_dirty = 0;
- do {
+ /*
+ * First pass - map what needs to be mapped, initiate reads
+ * on the boundaries if needed (i.e. if block is partially covered
+ * _and_ is not up-to-date _and_ is not new).
+ */
+ for(bh = head, block_start = 0; bh != head || !block_start;
+ block++, block_start=block_end, bh = bh->b_this_page) {
if (!bh)
BUG();
-
- if ((i < start_block) || (i > end_block)) {
- if (!buffer_uptodate(bh))
- partial = 1;
- goto skip;
- }
-
- /*
- * If the buffer is not up-to-date, we need to ask the low-level
- * FS to do something for us (we used to have assumptions about
- * the meaning of b_blocknr etc, that's bad).
- *
- * If "update" is set, that means that the low-level FS should
- * try to make sure that the block is up-to-date because we're
- * not going to fill it completely.
- */
+ block_end = block_start+blocksize;
+ if (block_end <= zerofrom)
+ continue;
+ if (block_start >= to)
+ break;
bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) {
err = inode->i_op->get_block(inode, block, bh, 1);
@@ -1455,71 +1418,73 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long
goto out;
unmap_underlying_metadata(bh);
}
-
- if (!buffer_uptodate(bh) && (start_offset || (end_bytes && (i == end_block)))) {
- if (buffer_new(bh)) {
- memset(kaddr + i*blocksize, 0, blocksize);
- } else {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- err = -EIO;
- if (!buffer_uptodate(bh))
- goto out;
- }
- }
-
- len = blocksize;
- if (start_offset) {
- len = start_bytes;
- start_offset = 0;
- } else if (end_bytes && (i == end_block)) {
- len = end_bytes;
- end_bytes = 0;
+ if (buffer_new(bh)) {
+ zeroto = block_end;
+ if (block_start < zerofrom)
+ zerofrom = block_start;
+ continue;
}
- if (target_buf >= kaddr + PAGE_SIZE)
- BUG();
- if (target_buf+len-1 >= kaddr + PAGE_SIZE)
- BUG();
- err = copy_from_user(target_buf, buf, len);
- target_buf += len;
- buf += len;
-
- /*
- * we dirty buffers only after copying the data into
- * the page - this way we can dirty the buffer even if
- * the bh is still doing IO.
- *
- * NOTE! This also does a direct dirty balace check,
- * rather than relying on bdflush just waking up every
- * once in a while. This is to catch (and slow down)
- * the processes that write tons of buffer..
- *
- * Note how we do NOT want to do this in the full block
- * case: full pages are flushed not by the people who
- * dirtied them, but by people who need memory. And we
- * should not penalize them for somebody else writing
- * lots of dirty pages.
- */
- set_bit(BH_Uptodate, &bh->b_state);
- if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
- __mark_dirty(bh, 0);
- need_balance_dirty = 1;
+ if (!buffer_uptodate(bh) &&
+ (block_start < zerofrom || block_end > to)) {
+ ll_rw_block(READ, 1, &bh);
+ *wait_bh++=bh;
}
-
- if (err) {
- err = -EFAULT;
+ }
+ /*
+ * If we issued read requests - let them complete.
+ */
+ while(wait_bh > wait) {
+ wait_on_buffer(*--wait_bh);
+ err = -EIO;
+ if (!buffer_uptodate(*wait_bh))
goto out;
+ }
+ /*
+ * Now we can copy the data.
+ */
+ if (zerofrom < from)
+ memset(kaddr+zerofrom, 0, from-zerofrom);
+ if (from < to)
+ err = copy_from_user(kaddr+from, buf, to-from);
+ if (to < zeroto)
+ memset(kaddr+to, 0, zeroto-to);
+ else
+ zeroto = to;
+ if (err < 0)
+ goto out;
+ /*
+ * Second pass: check if all out-of-range blocks are up-to-date
+ * and mark the rest up-to-date and dirty.
+ *
+ * NOTE! This also does a direct dirty balace check,
+ * rather than relying on bdflush just waking up every
+ * once in a while. This is to catch (and slow down)
+ * the processes that write tons of buffer..
+ *
+ * Note how we do NOT want to do this in the full block
+ * case: full pages are flushed not by the people who
+ * dirtied them, but by people who need memory. And we
+ * should not penalize them for somebody else writing
+ * lots of dirty pages.
+ */
+ for(bh = head, block_start = 0;
+ bh != head || !block_start;
+ block_start=block_end, bh = bh->b_this_page) {
+ block_end = block_start + blocksize;
+ if (block_end <= zerofrom || block_start >= zeroto) {
+ if (!buffer_uptodate(bh))
+ partial = 1;
+ } else {
+ set_bit(BH_Uptodate, &bh->b_state);
+ if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
+ __mark_dirty(bh, 0);
+ need_balance_dirty = 1;
+ }
}
-
-skip:
- i++;
- block++;
- bh = bh->b_this_page;
- } while (bh != head);
+ }
if (need_balance_dirty)
balance_dirty(bh->b_dev);
-
/*
* is this a partial write that happened to make all buffers
* uptodate then we can optimize away a bogus readpage() for
@@ -1529,183 +1494,48 @@ skip:
if (!partial)
SetPageUptodate(page);
kunmap(page);
- return bytes;
+ return 0;
out:
ClearPageUptodate(page);
kunmap(page);
return err;
}
-/*
- * For moronic filesystems that do not allow holes in file.
- * we allow offset==PAGE_SIZE, bytes==0
- */
-
-int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+int block_write_partial_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
- unsigned long block;
- int err, partial;
- unsigned long blocksize, start_block, end_block;
- unsigned long start_offset, start_bytes, end_bytes;
- unsigned long bbits, blocks, i, len;
- struct buffer_head *bh, *head;
- char * target_buf, *target_data;
- unsigned long data_offset = offset;
- int need_balance_dirty;
-
- offset = inode->i_size - (page->index << PAGE_CACHE_SHIFT);
- if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT))
- offset = 0;
- else if (offset >= data_offset)
- offset = data_offset;
- bytes += data_offset - offset;
-
- target_buf = (char *)page_address(page) + offset;
- target_data = (char *)page_address(page) + data_offset;
+ struct inode *inode = file->f_dentry->d_inode;
+ int err;
if (!PageLocked(page))
BUG();
-
- blocksize = inode->i_sb->s_blocksize;
- if (!page->buffers)
- create_empty_buffers(page, inode, blocksize);
- head = page->buffers;
-
- bbits = inode->i_sb->s_blocksize_bits;
- block = page->index << (PAGE_CACHE_SHIFT - bbits);
- blocks = PAGE_CACHE_SIZE >> bbits;
- start_block = offset >> bbits;
- end_block = (offset + bytes - 1) >> bbits;
- start_offset = offset & (blocksize - 1);
- start_bytes = blocksize - start_offset;
- if (start_bytes > bytes)
- start_bytes = bytes;
- end_bytes = (offset+bytes) & (blocksize - 1);
- if (end_bytes > bytes)
- end_bytes = bytes;
-
- if (offset < 0 || offset > PAGE_SIZE)
+ if (offset < 0 || offset >= PAGE_SIZE)
BUG();
if (bytes+offset < 0 || bytes+offset > PAGE_SIZE)
BUG();
- if (start_block < 0 || start_block > blocks)
- BUG();
- if (end_block < 0 || end_block >= blocks)
- BUG();
-
- i = 0;
- bh = head;
- partial = 0;
- need_balance_dirty = 0;
- do {
- if (!bh)
- BUG();
-
- if ((i < start_block) || (i > end_block)) {
- if (!buffer_uptodate(bh))
- partial = 1;
- goto skip;
- }
-
- /*
- * If the buffer is not up-to-date, we need to ask the low-level
- * FS to do something for us (we used to have assumptions about
- * the meaning of b_blocknr etc, that's bad).
- *
- * If "update" is set, that means that the low-level FS should
- * try to make sure that the block is up-to-date because we're
- * not going to fill it completely.
- */
- bh->b_end_io = end_buffer_io_sync;
- if (!buffer_mapped(bh)) {
- err = inode->i_op->get_block(inode, block, bh, 1);
- if (err)
- goto out;
- unmap_underlying_metadata(bh);
- }
-
- if (!buffer_uptodate(bh) && (start_offset || (end_bytes && (i == end_block)))) {
- if (buffer_new(bh)) {
- memset(bh->b_data, 0, bh->b_size);
- } else {
- ll_rw_block(READ, 1, &bh);
- wait_on_buffer(bh);
- err = -EIO;
- if (!buffer_uptodate(bh))
- goto out;
- }
- }
-
- len = blocksize;
- if (start_offset) {
- len = start_bytes;
- start_offset = 0;
- } else if (end_bytes && (i == end_block)) {
- len = end_bytes;
- end_bytes = 0;
- }
- err = 0;
- if (target_buf+len<=target_data)
- memset(target_buf, 0, len);
- else if (target_buf<target_data) {
- memset(target_buf, 0, target_data-target_buf);
- copy_from_user(target_data, buf,
- len+target_buf-target_data);
- } else
- err = copy_from_user(target_buf, buf, len);
- target_buf += len;
- buf += len;
-
- /*
- * we dirty buffers only after copying the data into
- * the page - this way we can dirty the buffer even if
- * the bh is still doing IO.
- *
- * NOTE! This also does a direct dirty balace check,
- * rather than relying on bdflush just waking up every
- * once in a while. This is to catch (and slow down)
- * the processes that write tons of buffer..
- *
- * Note how we do NOT want to do this in the full block
- * case: full pages are flushed not by the people who
- * dirtied them, but by people who need memory. And we
- * should not penalize them for somebody else writing
- * lots of dirty pages.
- */
- set_bit(BH_Uptodate, &bh->b_state);
- if (!test_and_set_bit(BH_Dirty, &bh->b_state)) {
- __mark_dirty(bh, 0);
- need_balance_dirty = 1;
- }
- if (err) {
- err = -EFAULT;
- goto out;
- }
+ err = block_write_range(inode, page, offset, bytes, buf);
+ return err ? err : bytes;
+}
-skip:
- i++;
- block++;
- bh = bh->b_this_page;
- } while (bh != head);
+/*
+ * For moronic filesystems that do not allow holes in file.
+ * we allow offset==PAGE_SIZE, bytes==0
+ */
- if (need_balance_dirty)
- balance_dirty(bh->b_dev);
+int block_write_cont_page(struct file *file, struct page *page, unsigned long offset, unsigned long bytes, const char * buf)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ int err;
+ unsigned zerofrom = offset;
- /*
- * is this a partial write that happened to make all buffers
- * uptodate then we can optimize away a bogus readpage() for
- * the next read(). Here we 'discover' wether the page went
- * uptodate as a result of this (potentially partial) write.
- */
- if (!partial)
- SetPageUptodate(page);
- return bytes;
-out:
- ClearPageUptodate(page);
- return err;
+ if (page->index > (inode->i_size >> PAGE_CACHE_SHIFT))
+ zerofrom = 0;
+ else if (page->index == (inode->i_size >> PAGE_CACHE_SHIFT) &&
+ offset > (inode->i_size & ~PAGE_CACHE_MASK))
+ zerofrom = inode->i_size & ~PAGE_CACHE_MASK;
+ err = block_write_zero_range(inode, page, zerofrom,offset,offset+bytes,
+ buf);
+ return err ? err : bytes;
}
@@ -1998,10 +1828,8 @@ int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
* mark_buffer_uptodate() functions propagate buffer state into the
* page struct once IO has completed.
*/
-int block_read_full_page(struct file * file, struct page * page)
+static inline int __block_read_full_page(struct inode *inode, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
- struct inode *inode = dentry->d_inode;
unsigned long iblock;
struct buffer_head *bh, *head, *arr[MAX_BUF_PER_PAGE];
unsigned int blocksize, blocks;
@@ -2060,6 +1888,47 @@ int block_read_full_page(struct file * file, struct page * page)
return 0;
}
+int block_read_full_page(struct dentry *dentry, struct page *page)
+{
+ return __block_read_full_page(dentry->d_inode, page);
+}
+
+int block_symlink(struct inode *inode, const char *symname, int len)
+{
+ struct page *page = grab_cache_page(&inode->i_data, 0);
+ mm_segment_t fs;
+ int err = -ENOMEM;
+
+ if (!page)
+ goto fail;
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ err = block_write_range(inode, page, 0, len-1, symname);
+ set_fs(fs);
+ inode->i_size = len-1;
+ if (err)
+ goto fail_write;
+ /*
+ * Notice that we are _not_ going to block here - end of page is
+ * unmapped, so this will only try to map the rest of page, see
+ * that it is unmapped (typically even will not look into inode -
+ * ->i_size will be enough for everything) and zero it out.
+ * OTOH it's obviously correct and should make the page up-to-date.
+ */
+ err = __block_read_full_page(inode, page);
+ wait_on_page(page);
+ page_cache_release(page);
+ if (err < 0)
+ goto fail;
+ mark_inode_dirty(inode);
+ return 0;
+fail_write:
+ UnlockPage(page);
+ page_cache_release(page);
+fail:
+ return err;
+}
+
/*
* Try to increase the number of buffers available: the size argument
* is used to determine what kind of buffers we want.
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index 883e34a91..794a8d263 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -80,11 +80,8 @@ struct inode_operations coda_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
coda_permission, /* permission */
- NULL, /* smap */
- NULL, /* update page */
coda_revalidate_inode /* revalidate */
};
diff --git a/fs/coda/file.c b/fs/coda/file.c
index d5cf1afef..d053258e8 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -26,7 +26,7 @@
#include <linux/coda_proc.h>
/* file operations */
-static int coda_readpage(struct file *file, struct page * page);
+static int coda_readpage(struct dentry *dentry, struct page * page);
static ssize_t coda_file_read(struct file *f, char *buf, size_t count, loff_t *off);
static ssize_t coda_file_write(struct file *f, const char *buf, size_t count, loff_t *off);
static int coda_file_mmap(struct file * file, struct vm_area_struct * vma);
@@ -50,10 +50,8 @@ struct inode_operations coda_file_inode_operations = {
NULL, /* get_block */
coda_readpage, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
coda_permission, /* permission */
- NULL, /* smap */
coda_revalidate_inode /* revalidate */
};
@@ -76,12 +74,10 @@ struct file_operations coda_file_operations = {
};
/* File file operations */
-static int coda_readpage(struct file * coda_file, struct page * page)
+static int coda_readpage(struct dentry * dentry, struct page * page)
{
- struct dentry *de = coda_file->f_dentry;
- struct inode *coda_inode = de->d_inode;
+ struct inode *coda_inode = dentry->d_inode;
struct dentry cont_dentry;
- struct file cont_file;
struct coda_inode_info *cii;
ENTRY;
@@ -91,17 +87,16 @@ static int coda_readpage(struct file * coda_file, struct page * page)
if ( ! cii->c_ovp ) {
printk("coda_readpage: no open inode for ino %ld, %s\n",
- coda_inode->i_ino, de->d_name.name);
+ coda_inode->i_ino, dentry->d_name.name);
return -ENXIO;
}
- coda_prepare_openfile(coda_inode, coda_file, cii->c_ovp,
- &cont_file, &cont_dentry);
+ cont_dentry.d_inode = cii->c_ovp;
CDEBUG(D_INODE, "coda ino: %ld, cached ino %ld, page offset: %lx\n",
coda_inode->i_ino, cii->c_ovp->i_ino, page->index);
- block_read_full_page(&cont_file, page);
+ block_read_full_page(&cont_dentry, page);
EXIT;
return 0;
}
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 3e6924f15..cec92b7f4 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -49,10 +49,8 @@ struct inode_operations coda_ioctl_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
coda_ioctl_permission, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index cfe0dbcb7..872370cf9 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -14,9 +14,6 @@
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/string.h>
#include <linux/coda.h>
#include <linux/coda_linux.h>
@@ -25,99 +22,34 @@
#include <linux/coda_cache.h>
#include <linux/coda_proc.h>
-static int coda_readlink(struct dentry *de, char *buffer, int length);
-static struct dentry *coda_follow_link(struct dentry *, struct dentry *,
- unsigned int);
-
-struct inode_operations coda_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- coda_readlink, /* readlink */
- coda_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static int coda_readlink(struct dentry *de, char *buffer, int length)
+static int coda_symlink_filler(struct dentry *dentry, struct page *page)
{
- struct inode *inode = de->d_inode;
- int len;
- int error;
- char *buf;
- struct coda_inode_info *cp;
- ENTRY;
-
- cp = ITOC(inode);
- coda_vfs_stat.readlink++;
-
- /* the maximum length we receive is len */
- if ( length > CODA_MAXPATHLEN )
- len = CODA_MAXPATHLEN;
- else
- len = length;
- CODA_ALLOC(buf, char *, len);
- if ( !buf )
- return -ENOMEM;
-
- error = venus_readlink(inode->i_sb, &(cp->c_fid), buf, &len);
-
- CDEBUG(D_INODE, "result %s\n", buf);
- if (! error) {
- copy_to_user(buffer, buf, len);
- put_user('\0', buffer + len);
- error = len;
- }
- if ( buf )
- CODA_FREE(buf, len);
- return error;
-}
-
-static struct dentry *coda_follow_link(struct dentry *de, struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = de->d_inode;
+ struct inode *inode = dentry->d_inode;
int error;
struct coda_inode_info *cnp;
- unsigned int len;
- char mem[CODA_MAXPATHLEN];
- char *path;
- ENTRY;
- CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
-
+ unsigned int len = PAGE_SIZE;
+ char *p = (char*)kmap(page);
+
cnp = ITOC(inode);
coda_vfs_stat.follow_link++;
- len = CODA_MAXPATHLEN;
- error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len);
-
- if (error) {
- dput(base);
- return ERR_PTR(error);
- }
- len = strlen(mem);
- path = kmalloc(len + 1, GFP_KERNEL);
- if (!path) {
- dput(base);
- return ERR_PTR(-ENOMEM);
- }
- memcpy(path, mem, len);
- path[len] = 0;
-
- base = lookup_dentry(path, base, follow);
- kfree(path);
- return base;
+ error = venus_readlink(inode->i_sb, &(cnp->c_fid), p, &len);
+ if (error)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return error;
}
+
+struct inode_operations coda_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: coda_symlink_filler
+};
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index 42b0fafca..046153362 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -285,7 +285,7 @@ int do_reset_coda_cache_inv_stats( ctl_table * table, int write,
}
int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
- int length, int dummy )
+ int length)
{
int len=0;
off_t begin;
@@ -352,7 +352,7 @@ int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
}
int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
- int length, int dummy )
+ int length)
{
int len=0;
int i;
@@ -399,7 +399,7 @@ int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
}
int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
- int length, int dummy )
+ int length)
{
int len=0;
off_t begin;
@@ -428,7 +428,7 @@ int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
}
int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
- int length, int dummy )
+ int length)
{
int len=0;
off_t begin;
@@ -492,7 +492,7 @@ void coda_sysctl_init()
reset_coda_cache_inv_stats();
#ifdef CONFIG_PROC_FS
- proc_fs_coda = create_proc_entry("coda", S_IFDIR, proc_root_fs);
+ proc_fs_coda = proc_mkdir("coda", proc_root_fs);
proc_fs_coda->owner = THIS_MODULE;
coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
diff --git a/fs/dcache.c b/fs/dcache.c
index f96f8cf7f..75a44c8d9 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -553,8 +553,7 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
/*
* An insecure source has sent us a dentry, here we verify it.
*
- * This is just to make knfsd able to have the dentry pointer
- * in the NFS file handle.
+ * This is used by ncpfs in its readdir implementation.
*
* NOTE! Do _not_ dereference the pointers before we have
* validated them. We can test the pointer values, but we
diff --git a/fs/devices.c b/fs/devices.c
index a436f60de..b44acfacf 100644
--- a/fs/devices.c
+++ b/fs/devices.c
@@ -281,10 +281,8 @@ struct inode_operations blkdev_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -338,10 +336,8 @@ struct inode_operations chrdev_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/devpts/root.c b/fs/devpts/root.c
index 5b5948e80..9b4d194f2 100644
--- a/fs/devpts/root.c
+++ b/fs/devpts/root.c
@@ -54,10 +54,8 @@ struct inode_operations devpts_root_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/dquot.c b/fs/dquot.c
index 2317af965..1efafcf51 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -21,6 +21,19 @@
* Revised list management to avoid races
* -- Bill Hawes, <whawes@star.net>, 9/98
*
+ * Fixed races in dquot_transfer(), dqget() and dquot_alloc_...().
+ * As the consequence the locking was moved from dquot_decr_...(),
+ * dquot_incr_...() to calling functions.
+ * invalidate_dquots() now writes modified dquots.
+ * Serialized quota_off() and quota_on() for mount point.
+ * Fixed a few bugs in grow_dquots.
+ * Fixed deadlock in write_dquot() - we no longer account quotas on
+ * quota files
+ * remove_dquot_ref() moved to inode.c - it now traverses through inodes
+ * add_dquot_ref() restarts after blocking
+ * Added check for bogus uid and fixed check for group in quotactl.
+ * Jan Kara, <jack@suse.cz>, sponsored by SuSE CR, 10-11/99
+ *
* (C) Copyright 1994 - 1997 Marco van Wieringen
*/
@@ -74,7 +87,7 @@ static kmem_cache_t *dquot_cachep;
*/
static struct dquot *inuse_list = NULL;
-LIST_HEAD(free_dquots);
+static LIST_HEAD(free_dquots);
static struct dquot *dquot_hash[NR_DQHASH];
static int dquot_updating[NR_DQHASH];
@@ -82,6 +95,9 @@ static struct dqstats dqstats;
static DECLARE_WAIT_QUEUE_HEAD(dquot_wait);
static DECLARE_WAIT_QUEUE_HEAD(update_wait);
+static void dqput(struct dquot *);
+static struct dquot *dqduplicate(struct dquot *);
+
static inline char is_enabled(struct vfsmount *vfsmnt, short type)
{
switch (type) {
@@ -166,7 +182,8 @@ static inline void remove_free_dquot(struct dquot *dquot)
{
/* sanity check */
if (list_empty(&dquot->dq_free)) {
- printk("remove_free_dquot: dquot not on free list??\n");
+ printk("remove_free_dquot: dquot not on the free list??\n");
+ return; /* J.K. Just don't do anything */
}
list_del(&dquot->dq_free);
INIT_LIST_HEAD(&dquot->dq_free);
@@ -226,16 +243,25 @@ static inline void unlock_dquot(struct dquot *dquot)
wake_up(&dquot->dq_wait);
}
+/*
+ * We don't have to be afraid of deadlocks as we never have quotas on quota files...
+ */
static void write_dquot(struct dquot *dquot)
{
short type = dquot->dq_type;
- struct file *filp = dquot->dq_mnt->mnt_dquot.files[type];
+ struct file *filp;
mm_segment_t fs;
loff_t offset;
ssize_t ret;
+ struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem;
lock_dquot(dquot);
- down(&dquot->dq_mnt->mnt_dquot.semaphore);
+ if (!dquot->dq_mnt) { /* Invalidated quota? */
+ unlock_dquot(dquot);
+ return;
+ }
+ down(sem);
+ filp = dquot->dq_mnt->mnt_dquot.files[type];
offset = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
@@ -253,40 +279,42 @@ static void write_dquot(struct dquot *dquot)
printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
kdevname(dquot->dq_dev));
- up(&dquot->dq_mnt->mnt_dquot.semaphore);
set_fs(fs);
-
+ up(sem);
unlock_dquot(dquot);
+
dqstats.writes++;
}
static void read_dquot(struct dquot *dquot)
{
- short type;
+ short type = dquot->dq_type;
struct file *filp;
mm_segment_t fs;
loff_t offset;
- type = dquot->dq_type;
filp = dquot->dq_mnt->mnt_dquot.files[type];
-
if (filp == (struct file *)NULL)
return;
lock_dquot(dquot);
- down(&dquot->dq_mnt->mnt_dquot.semaphore);
+ if (!dquot->dq_mnt) /* Invalidated quota? */
+ goto out_lock;
+ /* Now we are sure filp is valid - the dquot isn't invalidated */
+ down(&dquot->dq_mnt->mnt_dquot.dqio_sem);
offset = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
- up(&dquot->dq_mnt->mnt_dquot.semaphore);
+ up(&dquot->dq_mnt->mnt_dquot.dqio_sem);
set_fs(fs);
if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
dquot->dq_flags |= DQ_FAKE;
- unlock_dquot(dquot);
dqstats.reads++;
+out_lock:
+ unlock_dquot(dquot);
}
/*
@@ -306,10 +334,11 @@ void clear_dquot(struct dquot *dquot)
void invalidate_dquots(kdev_t dev, short type)
{
- struct dquot *dquot, *next = inuse_list;
+ struct dquot *dquot, *next;
int need_restart;
restart:
+ next = inuse_list; /* Here it is better. Otherwise the restart doesn't have any sense ;-) */
need_restart = 0;
while ((dquot = next) != NULL) {
next = dquot->dq_next;
@@ -317,6 +346,8 @@ restart:
continue;
if (dquot->dq_type != type)
continue;
+ if (!dquot->dq_mnt) /* Already invalidated entry? */
+ continue;
if (dquot->dq_flags & DQ_LOCKED) {
__wait_on_dquot(dquot);
@@ -329,6 +360,18 @@ restart:
continue;
if (dquot->dq_type != type)
continue;
+ if (!dquot->dq_mnt)
+ continue;
+ }
+ /*
+ * Because inodes needn't to be the only holders of dquot
+ * the quota needn't to be written to disk. So we write it
+ * ourselves before discarding the data just for sure...
+ */
+ if (dquot->dq_flags & DQ_MOD && dquot->dq_mnt)
+ {
+ write_dquot(dquot);
+ need_restart = 1; /* We slept on IO */
}
clear_dquot(dquot);
}
@@ -342,10 +385,11 @@ restart:
int sync_dquots(kdev_t dev, short type)
{
- struct dquot *dquot, *next = inuse_list;
+ struct dquot *dquot, *next, *ddquot;
int need_restart;
restart:
+ next = inuse_list;
need_restart = 0;
while ((dquot = next) != NULL) {
next = dquot->dq_next;
@@ -353,12 +397,16 @@ restart:
continue;
if (type != -1 && dquot->dq_type != type)
continue;
+ if (!dquot->dq_mnt) /* Invalidated? */
+ continue;
if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD)))
continue;
- wait_on_dquot(dquot);
- if (dquot->dq_flags & DQ_MOD)
- write_dquot(dquot);
+ if ((ddquot = dqduplicate(dquot)) == NODQUOT)
+ continue;
+ if (ddquot->dq_flags & DQ_MOD)
+ write_dquot(ddquot);
+ dqput(ddquot);
/* Set the flag for another pass. */
need_restart = 1;
}
@@ -373,7 +421,8 @@ restart:
return(0);
}
-void dqput(struct dquot *dquot)
+/* NOTE: If you change this function please check whether dqput_blocks() works right... */
+static void dqput(struct dquot *dquot)
{
if (!dquot)
return;
@@ -390,42 +439,45 @@ void dqput(struct dquot *dquot)
* checking and doesn't need to be written. It's just an empty
* dquot that is put back on to the freelist.
*/
- if (dquot->dq_mnt != (struct vfsmount *)NULL) {
+ if (dquot->dq_mnt)
dqstats.drops++;
we_slept:
- wait_on_dquot(dquot);
- if (dquot->dq_count > 1) {
- dquot->dq_count--;
- return;
- }
- if (dquot->dq_flags & DQ_MOD) {
- write_dquot(dquot);
- goto we_slept;
- }
+ if (dquot->dq_count > 1) {
+ /* We have more than one user... We can simply decrement use count */
+ dquot->dq_count--;
+ return;
+ }
+ if (dquot->dq_flags & DQ_LOCKED) {
+ printk(KERN_ERR "VFS: Locked quota to be put on the free list.\n");
+ dquot->dq_flags &= ~DQ_LOCKED;
+ }
+ if (dquot->dq_mnt && dquot->dq_flags & DQ_MOD) {
+ write_dquot(dquot);
+ goto we_slept;
}
/* sanity check */
if (!list_empty(&dquot->dq_free)) {
- printk("dqput: dquot already on free list??\n");
- }
- if (--dquot->dq_count == 0) {
- /* Place at end of LRU free queue */
- put_dquot_last(dquot);
- wake_up(&dquot_wait);
+ printk(KERN_ERR "dqput: dquot already on free list??\n");
+ dquot->dq_count--; /* J.K. Just decrementing use count seems safer... */
+ return;
}
-
- return;
+ dquot->dq_count--;
+ dquot->dq_flags &= ~DQ_MOD; /* Modified flag has no sense on free list */
+ /* Place at end of LRU free queue */
+ put_dquot_last(dquot);
+ wake_up(&dquot_wait);
}
-static void grow_dquots(void)
+static int grow_dquots(void)
{
struct dquot *dquot;
- int cnt = 32;
+ int cnt = 0;
- while (cnt > 0) {
+ while (cnt < 32) {
dquot = kmem_cache_alloc(dquot_cachep, SLAB_KERNEL);
if(!dquot)
- return;
+ return cnt;
nr_dquots++;
memset((caddr_t)dquot, 0, sizeof(struct dquot));
@@ -433,8 +485,9 @@ static void grow_dquots(void)
/* all dquots go on the inuse_list */
put_inuse(dquot);
put_dquot_head(dquot);
- cnt--;
+ cnt++;
}
+ return cnt;
}
static struct dquot *find_best_candidate_weighted(void)
@@ -446,6 +499,7 @@ static struct dquot *find_best_candidate_weighted(void)
while ((tmp = tmp->next) != &free_dquots && --limit) {
dquot = list_entry(tmp, struct dquot, dq_free);
+ /* This should never happen... */
if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD))
continue;
myscore = dquot->dq_referenced;
@@ -474,27 +528,16 @@ static inline struct dquot *find_best_free(void)
struct dquot *get_empty_dquot(void)
{
struct dquot *dquot;
- int count;
+ int shrink = 1; /* Number of times we should try to shrink dcache and icache */
repeat:
dquot = find_best_free();
if (!dquot)
goto pressure;
got_it:
- if (dquot->dq_flags & (DQ_LOCKED | DQ_MOD)) {
- wait_on_dquot(dquot);
- if (dquot->dq_flags & DQ_MOD)
- {
- if(dquot->dq_mnt != (struct vfsmount *)NULL)
- write_dquot(dquot);
- }
- /*
- * The dquot may be back in use now, so we
- * must recheck the free list.
- */
- goto repeat;
- }
- /* sanity check ... */
+ /* Sanity checks */
+ if (dquot->dq_flags & DQ_LOCKED)
+ printk(KERN_ERR "VFS: Locked dquot on the free list\n");
if (dquot->dq_count != 0)
printk(KERN_ERR "VFS: free dquot count=%d\n", dquot->dq_count);
@@ -505,10 +548,9 @@ got_it:
return dquot;
pressure:
- if (nr_dquots < max_dquots) {
- grow_dquots();
- goto repeat;
- }
+ if (nr_dquots < max_dquots)
+ if (grow_dquots())
+ goto repeat;
dquot = find_best_candidate_weighted();
if (dquot)
@@ -516,10 +558,11 @@ pressure:
/*
* Try pruning the dcache to free up some dquots ...
*/
- if (count) {
- printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
- prune_dcache(count);
- prune_icache(count);
+ if (shrink) {
+ printk(KERN_DEBUG "get_empty_dquot: pruning dcache and icache\n");
+ prune_dcache(128);
+ prune_icache(128);
+ shrink--;
goto repeat;
}
@@ -534,7 +577,7 @@ struct dquot *dqget(kdev_t dev, unsigned int id, short type)
struct dquot *dquot, *empty = NULL;
struct vfsmount *vfsmnt;
- if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || is_enabled(vfsmnt, type) == 0)
+ if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || !is_enabled(vfsmnt, type))
return(NODQUOT);
we_slept:
@@ -567,12 +610,67 @@ we_slept:
while (dquot_updating[hashent])
sleep_on(&update_wait);
+ if (!dquot->dq_mnt) { /* Has somebody invalidated entry under us? */
+ /*
+ * Do it as if the quota was invalidated before we started
+ */
+ dqput(dquot);
+ return NODQUOT;
+ }
dquot->dq_referenced++;
dqstats.lookups++;
return dquot;
}
+static struct dquot *dqduplicate(struct dquot *dquot)
+{
+ if (dquot == NODQUOT || !dquot->dq_mnt)
+ return NODQUOT;
+ dquot->dq_count++;
+ wait_on_dquot(dquot);
+ if (!dquot->dq_mnt) {
+ dquot->dq_count--;
+ return NODQUOT;
+ }
+ dquot->dq_referenced++;
+ dqstats.lookups++;
+ return dquot;
+}
+
+/* Check whether this inode is quota file */
+static inline int is_quotafile(struct inode *inode)
+{
+ int cnt;
+ struct vfsmount *vfsmnt;
+ struct file **files;
+
+ vfsmnt = lookup_vfsmnt(inode->i_dev);
+ if (!vfsmnt)
+ return 0;
+ files = vfsmnt->mnt_dquot.files;
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (files[cnt] && files[cnt]->f_dentry->d_inode == inode)
+ return 1;
+ return 0;
+}
+
+static int dqinit_needed(struct inode *inode, short type)
+{
+ int cnt;
+
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)))
+ return 0;
+ if (is_quotafile(inode))
+ return 0;
+ if (type != -1)
+ return inode->i_dquot[type] == NODQUOT;
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (inode->i_dquot[cnt] == NODQUOT)
+ return 1;
+ return 0;
+}
+
static void add_dquot_ref(kdev_t dev, short type)
{
struct super_block *sb = get_super(dev);
@@ -582,6 +680,7 @@ static void add_dquot_ref(kdev_t dev, short type)
if (!sb || !sb->dq_op)
return; /* nothing to do */
+restart:
file_list_lock();
for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
struct file *filp = list_entry(p, struct file, f_list);
@@ -590,84 +689,81 @@ static void add_dquot_ref(kdev_t dev, short type)
inode = filp->f_dentry->d_inode;
if (!inode)
continue;
- /* N.B. race problem -- filp could become unused */
- if (filp->f_mode & FMODE_WRITE) {
+ if (filp->f_mode & FMODE_WRITE && dqinit_needed(inode, type)) {
file_list_unlock();
sb->dq_op->initialize(inode, type);
inode->i_flags |= S_QUOTA;
- file_list_lock();
+ /* As we may have blocked we had better restart... */
+ goto restart;
}
}
file_list_unlock();
}
-static void reset_dquot_ptrs(kdev_t dev, short type)
+/* Return 0 if dqput() won't block (note that 1 doesn't necessarily mean blocking) */
+static inline int dqput_blocks(struct dquot *dquot)
{
- struct super_block *sb = get_super(dev);
- struct list_head *p;
- struct inode *inode;
- struct dquot *dquot;
+ if (dquot->dq_count == 1)
+ return 1;
+ return 0;
+}
+
+/* Remove references to dquots from inode - add dquot to list for freeing if needed */
+int remove_inode_dquot_ref(struct inode *inode, short type, struct list_head *tofree_head)
+{
+ struct dquot *dquot = inode->i_dquot[type];
int cnt;
- if (!sb || !sb->dq_op)
- return; /* nothing to do */
+ inode->i_dquot[type] = NODQUOT;
+ /* any other quota in use? */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (inode->i_dquot[cnt] != NODQUOT)
+ goto put_it;
+ }
+ inode->i_flags &= ~S_QUOTA;
+put_it:
+ if (dquot != NODQUOT)
+ if (dqput_blocks(dquot)) {
+ if (dquot->dq_count != 1)
+ printk(KERN_WARNING "VFS: Adding dquot with dq_count %d to dispose list.\n", dquot->dq_count);
+ list_add(&dquot->dq_free, tofree_head); /* As dquot must have currently users it can't be on the free list... */
+ return 1;
+ }
+ else
+ dqput(dquot); /* We have guaranteed we won't block */
+ return 0;
+}
-restart:
- /* free any quota for unused dentries */
- shrink_dcache_sb(sb);
+/* Free list of dquots - called from inode.c */
+void put_dquot_list(struct list_head *tofree_head)
+{
+ struct list_head *act_head = tofree_head;
+ struct dquot *dquot;
- file_list_lock();
- for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
- struct file *filp = list_entry(p, struct file, f_list);
- if (!filp->f_dentry)
- continue;
- inode = filp->f_dentry->d_inode;
- if (!inode)
- continue;
- /*
- * Note: we restart after each blocking operation,
- * as the inuse_filps list may have changed.
- */
- if (IS_QUOTAINIT(inode)) {
- dquot = inode->i_dquot[type];
- inode->i_dquot[type] = NODQUOT;
- /* any other quota in use? */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] != NODQUOT)
- goto put_it;
- }
- inode->i_flags &= ~S_QUOTA;
- put_it:
- if (dquot != NODQUOT) {
- file_list_unlock();
- dqput(dquot);
- /* we may have blocked ... */
- goto restart;
- }
- }
+ /* So now we have dquots on the list... Just free them */
+ while (act_head != tofree_head) {
+ dquot = list_entry(act_head, struct dquot, dq_free);
+ act_head = act_head->next;
+ list_del(&dquot->dq_free); /* Remove dquot from the list so we won't have problems... */
+ INIT_LIST_HEAD(&dquot->dq_free);
+ dqput(dquot);
}
- file_list_unlock();
}
static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
{
- lock_dquot(dquot);
dquot->dq_curinodes += number;
dquot->dq_flags |= DQ_MOD;
- unlock_dquot(dquot);
}
static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
{
- lock_dquot(dquot);
dquot->dq_curblocks += number;
dquot->dq_flags |= DQ_MOD;
- unlock_dquot(dquot);
}
static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
{
- lock_dquot(dquot);
if (dquot->dq_curinodes > number)
dquot->dq_curinodes -= number;
else
@@ -676,12 +772,10 @@ static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
dquot->dq_itime = (time_t) 0;
dquot->dq_flags &= ~DQ_INODES;
dquot->dq_flags |= DQ_MOD;
- unlock_dquot(dquot);
}
static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
{
- lock_dquot(dquot);
if (dquot->dq_curblocks > number)
dquot->dq_curblocks -= number;
else
@@ -690,113 +784,115 @@ static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
dquot->dq_btime = (time_t) 0;
dquot->dq_flags &= ~DQ_BLKS;
dquot->dq_flags |= DQ_MOD;
- unlock_dquot(dquot);
}
-static inline char need_print_warning(short type, uid_t initiator, struct dquot *dquot)
+static inline int need_print_warning(struct dquot *dquot, int flag)
{
- switch (type) {
+ switch (dquot->dq_type) {
case USRQUOTA:
- return(initiator == dquot->dq_id);
+ return current->fsuid == dquot->dq_id && !(dquot->dq_flags & flag);
case GRPQUOTA:
- return(initiator == dquot->dq_id);
+ return in_group_p(dquot->dq_id) && !(dquot->dq_flags & flag);
}
- return(0);
+ return 0;
}
-static inline char ignore_hardlimit(struct dquot *dquot, uid_t initiator)
+static void print_warning(struct dquot *dquot, int flag, char *fmtstr, ...)
{
- return(initiator == 0 && dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type] == 0);
+ va_list args;
+
+ if (!need_print_warning(dquot, flag))
+ return;
+ va_start(args, fmtstr);
+ vsprintf(quotamessage, fmtstr, args);
+ va_end(args);
+ tty_write_message(current->tty, quotamessage);
+ dquot->dq_flags |= flag;
}
-static int check_idq(struct dquot *dquot, short type, u_long short inodes, uid_t initiator,
- struct tty_struct *tty)
+static inline char ignore_hardlimit(struct dquot *dquot)
{
+ return capable(CAP_SYS_RESOURCE) && !dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type];
+}
+
+static int check_idq(struct dquot *dquot, u_long inodes)
+{
+ short type = dquot->dq_type;
+
if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
- return(QUOTA_OK);
+ return QUOTA_OK;
if (dquot->dq_ihardlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit &&
- !ignore_hardlimit(dquot, initiator)) {
- if ((dquot->dq_flags & DQ_INODES) == 0 &&
- need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s file limit reached\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- dquot->dq_flags |= DQ_INODES;
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ print_warning(dquot, DQ_INODES, "%s: write failed, %s file limit reached\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}
if (dquot->dq_isoftlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime &&
- !ignore_hardlimit(dquot, initiator)) {
- if (need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ print_warning(dquot, DQ_INODES, "%s: warning, %s file quota exceeded too long.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}
if (dquot->dq_isoftlimit &&
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime == 0) {
- if (need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s file quota exceeded\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
+ print_warning(dquot, 0, "%s: warning, %s file quota exceeded\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
}
- return(QUOTA_OK);
+ return QUOTA_OK;
}
-static int check_bdq(struct dquot *dquot, short type, u_long blocks, uid_t initiator,
- struct tty_struct *tty, char warn)
+static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc)
{
+ short type = dquot->dq_type;
+
if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
- return(QUOTA_OK);
+ return QUOTA_OK;
if (dquot->dq_bhardlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit &&
- !ignore_hardlimit(dquot, initiator)) {
- if (warn && (dquot->dq_flags & DQ_BLKS) == 0 &&
- need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s disk limit reached.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- dquot->dq_flags |= DQ_BLKS;
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ if (!prealloc)
+ print_warning(dquot, DQ_BLKS, "%s: write failed, %s disk limit reached.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}
if (dquot->dq_bsoftlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime &&
- !ignore_hardlimit(dquot, initiator)) {
- if (warn && need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
- }
- return(NO_QUOTA);
+ !ignore_hardlimit(dquot)) {
+ if (!prealloc)
+ print_warning(dquot, DQ_BLKS, "%s: write failed, %s disk quota exceeded too long.\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ return NO_QUOTA;
}
if (dquot->dq_bsoftlimit &&
(dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
dquot->dq_btime == 0) {
- if (warn && need_print_warning(type, initiator, dquot)) {
- sprintf(quotamessage, "%s: warning, %s disk quota exceeded\n",
- dquot->dq_mnt->mnt_dirname, quotatypes[type]);
- tty_write_message(tty, quotamessage);
+ if (!prealloc) {
+ print_warning(dquot, 0, "%s: warning, %s disk quota exceeded\n",
+ dquot->dq_mnt->mnt_dirname, quotatypes[type]);
+ dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
}
- dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[type];
+ else
+ /*
+ * We don't allow preallocation to exceed softlimit so exceeding will
+ * be always printed
+ */
+ return NO_QUOTA;
}
- return(QUOTA_OK);
+ return QUOTA_OK;
}
/*
@@ -874,9 +970,11 @@ static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk)
if (dquot == NODQUOT)
goto out;
+ lock_dquot(dquot); /* We must protect against invalidating the quota */
error = -EFAULT;
if (dqblk && !copy_to_user(dqblk, &dquot->dq_dqb, sizeof(struct dqblk)))
error = 0;
+ unlock_dquot(dquot);
dqput(dquot);
out:
return error;
@@ -917,14 +1015,14 @@ static int quota_root_squash(kdev_t dev, short type, int *addr)
* This is a simple algorithm that calculates the size of a file in blocks.
* This is only used on filesystems that do not have an i_blocks count.
*/
-static u_long isize_to_blocks(size_t isize, size_t blksize)
+static u_long isize_to_blocks(loff_t isize, size_t blksize_bits)
{
u_long blocks;
u_long indirect;
- if (!blksize)
- blksize = BLOCK_SIZE;
- blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
+ if (!blksize_bits)
+ blksize_bits = BLOCK_SIZE_BITS;
+ blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0);
if (blocks > 10) {
indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
if (blocks > (10 + 256)) {
@@ -934,7 +1032,7 @@ static u_long isize_to_blocks(size_t isize, size_t blksize)
}
blocks += indirect;
}
- return(blocks);
+ return blocks;
}
/*
@@ -951,6 +1049,9 @@ void dquot_initialize(struct inode *inode, short type)
if (S_ISREG(inode->i_mode) ||
S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)) {
+ /* We don't want to have quotas on quota files - nasty deadlocks possible */
+ if (is_quotafile(inode))
+ return;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
@@ -968,6 +1069,8 @@ void dquot_initialize(struct inode *inode, short type)
break;
}
dquot = dqget(inode->i_dev, id, cnt);
+ if (dquot == NODQUOT)
+ continue;
if (inode->i_dquot[cnt] != NODQUOT) {
dqput(dquot);
continue;
@@ -1002,50 +1105,73 @@ void dquot_drop(struct inode *inode)
/*
* Note: this is a blocking operation.
*/
-int dquot_alloc_block(const struct inode *inode, unsigned long number, uid_t initiator,
- char warn)
+int dquot_alloc_block(const struct inode *inode, unsigned long number, char warn)
{
- unsigned short cnt;
- struct tty_struct *tty = current->tty;
+ int cnt;
+ struct dquot *dquot[MAXQUOTAS];
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ dquot[cnt] = dqduplicate(inode->i_dquot[cnt]);
+ if (dquot[cnt] == NODQUOT)
continue;
- if (check_bdq(inode->i_dquot[cnt], cnt, number, initiator, tty, warn))
- return(NO_QUOTA);
+ lock_dquot(dquot[cnt]);
+ if (check_bdq(dquot[cnt], number, warn))
+ goto put_all;
}
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ if (dquot[cnt] == NODQUOT)
continue;
- dquot_incr_blocks(inode->i_dquot[cnt], number);
+ dquot_incr_blocks(dquot[cnt], number);
+ unlock_dquot(dquot[cnt]);
+ dqput(dquot[cnt]);
}
- return(QUOTA_OK);
+ return QUOTA_OK;
+put_all:
+ for (; cnt >= 0; cnt--) {
+ if (dquot[cnt] == NODQUOT)
+ continue;
+ unlock_dquot(dquot[cnt]);
+ dqput(dquot[cnt]);
+ }
+ return NO_QUOTA;
}
/*
* Note: this is a blocking operation.
*/
-int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t initiator)
+int dquot_alloc_inode(const struct inode *inode, unsigned long number)
{
- unsigned short cnt;
- struct tty_struct *tty = current->tty;
+ int cnt;
+ struct dquot *dquot[MAXQUOTAS];
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ dquot[cnt] = dqduplicate(inode -> i_dquot[cnt]);
+ if (dquot[cnt] == NODQUOT)
continue;
- if (check_idq(inode->i_dquot[cnt], cnt, number, initiator, tty))
- return(NO_QUOTA);
+ lock_dquot(dquot[cnt]);
+ if (check_idq(dquot[cnt], number))
+ goto put_all;
}
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ if (dquot[cnt] == NODQUOT)
continue;
- dquot_incr_inodes(inode->i_dquot[cnt], number);
+ dquot_incr_inodes(dquot[cnt], number);
+ unlock_dquot(dquot[cnt]);
+ dqput(dquot[cnt]);
}
- return(QUOTA_OK);
+ return QUOTA_OK;
+put_all:
+ for (; cnt >= 0; cnt--) {
+ if (dquot[cnt] == NODQUOT)
+ continue;
+ unlock_dquot(dquot[cnt]);
+ dqput(dquot[cnt]);
+ }
+ return NO_QUOTA;
}
/*
@@ -1054,11 +1180,14 @@ int dquot_alloc_inode(const struct inode *inode, unsigned long number, uid_t ini
void dquot_free_block(const struct inode *inode, unsigned long number)
{
unsigned short cnt;
+ struct dquot *dquot;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ dquot = inode->i_dquot[cnt];
+ if (dquot == NODQUOT)
continue;
- dquot_decr_blocks(inode->i_dquot[cnt], number);
+ wait_on_dquot(dquot);
+ dquot_decr_blocks(dquot, number);
}
}
@@ -1068,11 +1197,14 @@ void dquot_free_block(const struct inode *inode, unsigned long number)
void dquot_free_inode(const struct inode *inode, unsigned long number)
{
unsigned short cnt;
+ struct dquot *dquot;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] == NODQUOT)
+ dquot = inode->i_dquot[cnt];
+ if (dquot == NODQUOT)
continue;
- dquot_decr_inodes(inode->i_dquot[cnt], number);
+ wait_on_dquot(dquot);
+ dquot_decr_inodes(dquot, number);
}
}
@@ -1081,21 +1213,24 @@ void dquot_free_inode(const struct inode *inode, unsigned long number)
*
* Note: this is a blocking operation.
*/
-int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid_t initiator)
+int dquot_transfer(struct dentry *dentry, struct iattr *iattr)
{
+ struct inode *inode = dentry -> d_inode;
unsigned long blocks;
struct dquot *transfer_from[MAXQUOTAS];
struct dquot *transfer_to[MAXQUOTAS];
- struct tty_struct *tty = current->tty;
short cnt, disc;
+ int error = -EDQUOT;
+ if (!inode)
+ return -ENOENT;
/*
* Find out if this filesystem uses i_blocks.
*/
- if (inode->i_blksize == 0)
- blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE);
+ if (!inode->i_sb || !inode->i_sb->s_blocksize)
+ blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS);
else
- blocks = (inode->i_blocks / 2);
+ blocks = (inode->i_blocks >> 1);
/*
* Build the transfer_from and transfer_to lists and check quotas to see
@@ -1112,27 +1247,60 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid
case USRQUOTA:
if (inode->i_uid == iattr->ia_uid)
continue;
- transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_uid : inode->i_uid, cnt);
- transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_uid : iattr->ia_uid, cnt);
+ /* We can get transfer_from from inode, can't we? */
+ transfer_from[cnt] = dqget(inode->i_dev, inode->i_uid, cnt);
+ transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_uid, cnt);
break;
case GRPQUOTA:
if (inode->i_gid == iattr->ia_gid)
continue;
- transfer_from[cnt] = dqget(inode->i_dev, (direction) ? iattr->ia_gid : inode->i_gid, cnt);
- transfer_to[cnt] = dqget(inode->i_dev, (direction) ? inode->i_gid : iattr->ia_gid, cnt);
+ transfer_from[cnt] = dqget(inode->i_dev, inode->i_gid, cnt);
+ transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_gid, cnt);
break;
}
- if (check_idq(transfer_to[cnt], cnt, 1, initiator, tty) == NO_QUOTA ||
- check_bdq(transfer_to[cnt], cnt, blocks, initiator, tty, 0) == NO_QUOTA) {
- for (disc = 0; disc <= cnt; disc++) {
- dqput(transfer_from[disc]);
- dqput(transfer_to[disc]);
+ /* Something bad (eg. quotaoff) happened while we were sleeping? */
+ if (transfer_from[cnt] == NODQUOT || transfer_to[cnt] == NODQUOT)
+ {
+ if (transfer_from[cnt] != NODQUOT) {
+ dqput(transfer_from[cnt]);
+ transfer_from[cnt] = NODQUOT;
+ }
+ if (transfer_to[cnt] != NODQUOT) {
+ dqput(transfer_to[cnt]);
+ transfer_to[cnt] = NODQUOT;
}
- return(NO_QUOTA);
+ continue;
+ }
+ /*
+ * We have to lock the quotas to prevent races...
+ */
+ if (transfer_from[cnt] < transfer_to[cnt])
+ {
+ lock_dquot(transfer_from[cnt]);
+ lock_dquot(transfer_to[cnt]);
+ }
+ else
+ {
+ lock_dquot(transfer_to[cnt]);
+ lock_dquot(transfer_from[cnt]);
+ }
+
+ /*
+ * The entries might got invalidated while locking. The second
+ * dqget() could block and so the first structure might got
+ * invalidated or locked...
+ */
+ if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt ||
+ check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
+ check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
+ cnt++;
+ goto put_all;
}
}
+ if ((error = notify_change(dentry, iattr)))
+ goto put_all;
/*
* Finally perform the needed transfer from transfer_from to transfer_to,
* and release any pointers to dquots not needed anymore.
@@ -1144,28 +1312,39 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr, char direction, uid
if (transfer_from[cnt] == NODQUOT && transfer_to[cnt] == NODQUOT)
continue;
- if (transfer_from[cnt] != NODQUOT) {
- dquot_decr_inodes(transfer_from[cnt], 1);
- dquot_decr_blocks(transfer_from[cnt], blocks);
- }
+ dquot_decr_inodes(transfer_from[cnt], 1);
+ dquot_decr_blocks(transfer_from[cnt], blocks);
- if (transfer_to[cnt] != NODQUOT) {
- dquot_incr_inodes(transfer_to[cnt], 1);
- dquot_incr_blocks(transfer_to[cnt], blocks);
- }
+ dquot_incr_inodes(transfer_to[cnt], 1);
+ dquot_incr_blocks(transfer_to[cnt], blocks);
+ unlock_dquot(transfer_from[cnt]);
+ dqput(transfer_from[cnt]);
if (inode->i_dquot[cnt] != NODQUOT) {
struct dquot *temp = inode->i_dquot[cnt];
inode->i_dquot[cnt] = transfer_to[cnt];
+ unlock_dquot(transfer_to[cnt]);
dqput(temp);
- dqput(transfer_from[cnt]);
} else {
- dqput(transfer_from[cnt]);
+ unlock_dquot(transfer_to[cnt]);
dqput(transfer_to[cnt]);
}
}
- return(QUOTA_OK);
+ return 0;
+put_all:
+ for (disc = 0; disc < cnt; disc++) {
+ /* There should be none or both pointers set but... */
+ if (transfer_to[disc] != NODQUOT) {
+ unlock_dquot(transfer_to[disc]);
+ dqput(transfer_to[disc]);
+ }
+ if (transfer_from[disc] != NODQUOT) {
+ unlock_dquot(transfer_from[disc]);
+ dqput(transfer_from[disc]);
+ }
+ }
+ return error;
}
@@ -1221,6 +1400,9 @@ static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type)
}
}
+/* Function in inode.c - remove pointers to dquots in icache */
+extern void remove_dquot_ref(kdev_t, short);
+
/*
* Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
*/
@@ -1229,48 +1411,57 @@ int quota_off(kdev_t dev, short type)
struct vfsmount *vfsmnt;
struct file *filp;
short cnt;
+ int enabled = 0;
+
+ /* We don't need to search for vfsmnt each time - umount has to wait for us */
+ vfsmnt = lookup_vfsmnt(dev);
+ if (!vfsmnt || !vfsmnt->mnt_sb)
+ goto out;
+ /* We need to serialize quota_off() for device */
+ down(&vfsmnt->mnt_dquot.dqoff_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
-
- vfsmnt = lookup_vfsmnt(dev);
- if (!vfsmnt)
- goto out;
- if (!vfsmnt->mnt_sb)
- goto out;
if (!is_enabled(vfsmnt, cnt))
continue;
reset_enable_flags(vfsmnt, cnt);
/* Note: these are blocking operations */
- reset_dquot_ptrs(dev, cnt);
+ remove_dquot_ref(dev, cnt);
invalidate_dquots(dev, cnt);
+ /* Wait for any pending IO - remove me as soon as invalidate is more polite */
+ down(&vfsmnt->mnt_dquot.dqio_sem);
filp = vfsmnt->mnt_dquot.files[cnt];
vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL;
vfsmnt->mnt_dquot.inode_expire[cnt] = 0;
vfsmnt->mnt_dquot.block_expire[cnt] = 0;
+ up(&vfsmnt->mnt_dquot.dqio_sem);
fput(filp);
- }
+ }
/*
* Check whether any quota is still enabled,
* and if not clear the dq_op pointer.
*/
- vfsmnt = lookup_vfsmnt(dev);
- if (vfsmnt && vfsmnt->mnt_sb) {
- int enabled = 0;
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- enabled |= is_enabled(vfsmnt, cnt);
- if (!enabled)
- vfsmnt->mnt_sb->dq_op = NULL;
- }
-
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ enabled |= is_enabled(vfsmnt, cnt);
+ if (!enabled)
+ vfsmnt->mnt_sb->dq_op = NULL;
+ up(&vfsmnt->mnt_dquot.dqoff_sem);
out:
return(0);
}
+static inline int check_quotafile_size(loff_t size)
+{
+ ulong blocks = size >> BLOCK_SIZE_BITS;
+ size_t off = size & (BLOCK_SIZE - 1);
+
+ return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
+}
+
int quota_on(kdev_t dev, short type, char *path)
{
struct file *f;
@@ -1287,47 +1478,52 @@ int quota_on(kdev_t dev, short type, char *path)
if (is_enabled(vfsmnt, type))
return -EBUSY;
- mnt_dquot = &vfsmnt->mnt_dquot;
+ mnt_dquot = &vfsmnt->mnt_dquot;
+ down(&mnt_dquot->dqoff_sem);
tmp = getname(path);
error = PTR_ERR(tmp);
if (IS_ERR(tmp))
- return error;
+ goto out_lock;
f = filp_open(tmp, O_RDWR, 0600);
putname(tmp);
- if (IS_ERR(f))
- return PTR_ERR(f);
- /* sanity checks */
+ error = PTR_ERR(f);
+ if (IS_ERR(f))
+ goto out_lock;
error = -EIO;
if (!f->f_op->read && !f->f_op->write)
- goto cleanup;
+ goto out_f;
inode = f->f_dentry->d_inode;
error = -EACCES;
if (!S_ISREG(inode->i_mode))
- goto cleanup;
+ goto out_f;
error = -EINVAL;
- if (inode->i_size == 0 || (inode->i_size % sizeof(struct dqblk)) != 0)
- goto cleanup;
+ if (inode->i_size == 0 || !check_quotafile_size(inode->i_size))
+ goto out_f;
+ dquot_drop(inode); /* We don't want quota on quota files */
- /* OK, there we go */
set_enable_flags(vfsmnt, type);
mnt_dquot->files[type] = f;
dquot = dqget(dev, 0, type);
- mnt_dquot->inode_expire[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
- mnt_dquot->block_expire[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
+ mnt_dquot->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
+ mnt_dquot->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
dqput(dquot);
vfsmnt->mnt_sb->dq_op = &dquot_operations;
add_dquot_ref(dev, type);
- return(0);
+ up(&mnt_dquot->dqoff_sem);
+ return 0;
-cleanup:
- fput(f);
- return error;
+out_f:
+ filp_close(f, NULL);
+out_lock:
+ up(&mnt_dquot->dqoff_sem);
+
+ return error;
}
/*
@@ -1348,6 +1544,9 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
if ((u_int) type >= MAXQUOTAS)
goto out;
+ if (id & ~0xFFFF)
+ goto out;
+
ret = -EPERM;
switch (cmds) {
case Q_SYNC:
@@ -1355,7 +1554,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
break;
case Q_GETQUOTA:
if (((type == USRQUOTA && current->euid != id) ||
- (type == GRPQUOTA && current->egid != id)) &&
+ (type == GRPQUOTA && in_egroup_p(id))) &&
!capable(CAP_SYS_RESOURCE))
goto out;
break;
@@ -1365,7 +1564,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
}
ret = -EINVAL;
- dev = 0;
+ dev = NODEV;
if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) {
mode_t mode;
struct dentry * dentry;
diff --git a/fs/efs/dir.c b/fs/efs/dir.c
index 29f2ebbc3..05a3334f7 100644
--- a/fs/efs/dir.c
+++ b/fs/efs/dir.c
@@ -43,10 +43,8 @@ struct inode_operations efs_dir_inode_operations = {
efs_get_block, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/efs/file.c b/fs/efs/file.c
index b86965f8f..adcc03120 100644
--- a/fs/efs/file.c
+++ b/fs/efs/file.c
@@ -94,9 +94,7 @@ struct inode_operations efs_file_inode_operations = {
efs_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/efs/symlink.c b/fs/efs/symlink.c
index 69ddda45b..6bfc16be7 100644
--- a/fs/efs/symlink.c
+++ b/fs/efs/symlink.c
@@ -7,99 +7,49 @@
*/
#include <linux/string.h>
-#include <linux/malloc.h>
#include <linux/efs_fs.h>
+#include <linux/pagemap.h>
-static int efs_readlink(struct dentry *, char *, int);
-static struct dentry * efs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-struct inode_operations efs_symlink_inode_operations = {
- NULL, /* no symlink file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- efs_readlink, /* readlink */
- efs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static char *efs_linktarget(struct inode *in, int *len) {
- char *name;
+static int efs_symlink_readpage(struct dentry *dentry, struct page *page)
+{
+ char *link = (char*)kmap(page);
struct buffer_head * bh;
- efs_block_t size = in->i_size;
-
- if (size > 2 * EFS_BLOCKSIZE) {
- printk(KERN_ERR "EFS: linktarget(): name too long: %lu\n", in->i_size);
- return NULL;
- }
+ struct inode * inode = dentry->d_inode;
+ efs_block_t size = inode->i_size;
+ int err;
- if (!(name = kmalloc(size + 1, GFP_KERNEL)))
- return NULL;
+ err = -ENAMETOOLONG;
+ if (size > 2 * EFS_BLOCKSIZE)
+ goto fail;
/* read first 512 bytes of link target */
- bh = bread(in->i_dev, efs_bmap(in, 0), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 0));
- return NULL;
- }
-
- memcpy(name, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
+ err = -EIO;
+ bh = bread(inode->i_dev, efs_bmap(inode, 0), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link, bh->b_data, (size > EFS_BLOCKSIZE) ? EFS_BLOCKSIZE : size);
brelse(bh);
-
if (size > EFS_BLOCKSIZE) {
- bh = bread(in->i_dev, efs_bmap(in, 1), EFS_BLOCKSIZE);
- if (!bh) {
- kfree(name);
- printk(KERN_ERR "EFS: linktarget(): couldn't read block %d\n", efs_bmap(in, 1));
- return NULL;
- }
- memcpy(name + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
+ bh = bread(inode->i_dev, efs_bmap(inode, 1), EFS_BLOCKSIZE);
+ if (!bh)
+ goto fail;
+ memcpy(link + EFS_BLOCKSIZE, bh->b_data, size - EFS_BLOCKSIZE);
brelse(bh);
}
-
- name[size] = (char) 0;
- if (len) *len = size;
-
- return name;
-}
-
-static struct dentry *efs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow) {
- char *name;
- struct inode *inode = dentry->d_inode;
-
- if (!(name = efs_linktarget(inode, NULL))) {
- dput(base);
- return ERR_PTR(-ELOOP);
- }
- base = lookup_dentry(name, base, follow);
- kfree(name);
-
- return base;
-}
-
-static int efs_readlink(struct dentry * dir, char * buf, int bufsiz) {
- int rc;
- char *name;
- struct inode *inode = dir->d_inode;
-
- if (!(name = efs_linktarget(inode, &bufsiz))) return 0;
- rc = copy_to_user(buf, name, bufsiz) ? -EFAULT : bufsiz;
- kfree(name);
-
- return rc;
+ link[size] = '\0';
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
}
+struct inode_operations efs_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: efs_symlink_readpage
+};
diff --git a/fs/exec.c b/fs/exec.c
index a7ca3dfaa..e329252d1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -35,7 +35,7 @@
#include <linux/highmem.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#ifdef CONFIG_KMOD
@@ -371,6 +371,7 @@ static int exec_mmap(void)
if (mm) {
struct mm_struct *active_mm = current->active_mm;
+ init_new_context(current, mm);
current->mm = mm;
current->active_mm = mm;
activate_mm(active_mm, mm);
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 5ec306fdf..26db0a623 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -7,7 +7,6 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c
index e0f7a655c..6c232ce79 100644
--- a/fs/ext2/balloc.c
+++ b/fs/ext2/balloc.c
@@ -11,7 +11,6 @@
* David S. Miller (davem@caip.rutgers.edu), 1995
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
diff --git a/fs/ext2/bitmap.c b/fs/ext2/bitmap.c
index ddd0ac12c..c0ffb68cd 100644
--- a/fs/ext2/bitmap.c
+++ b/fs/ext2/bitmap.c
@@ -7,7 +7,6 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
-#include <linux/module.h>
#include <linux/fs.h>
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c
index e1f45105e..2cc69ee5b 100644
--- a/fs/ext2/dir.c
+++ b/fs/ext2/dir.c
@@ -18,7 +18,6 @@
* David S. Miller (davem@caip.rutgers.edu), 1995
*/
-#include <linux/module.h>
#include <linux/fs.h>
@@ -67,10 +66,8 @@ struct inode_operations ext2_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
ext2_permission, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index 987b55f94..5ebba9da1 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -18,7 +18,6 @@
* (jj@sunsite.ms.mff.cuni.cz)
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
@@ -177,9 +176,7 @@ struct inode_operations ext2_file_inode_operations = {
ext2_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
ext2_truncate, /* truncate */
ext2_permission, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
diff --git a/fs/ext2/fsync.c b/fs/ext2/fsync.c
index cd12a68bd..f4e02c2e8 100644
--- a/fs/ext2/fsync.c
+++ b/fs/ext2/fsync.c
@@ -22,7 +22,6 @@
* we can depend on generic_block_fdatasync() to sync the data blocks.
*/
-#include <linux/module.h>
#include <linux/fs.h>
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index d6953e4cb..d519f6001 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -12,7 +12,6 @@
* David S. Miller (davem@caip.rutgers.edu), 1995
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
@@ -474,7 +473,7 @@ repeat:
if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
inode->i_flags |= MS_SYNCHRONOUS;
insert_inode_hash(inode);
- inode->i_generation++;
+ inode->i_generation = event++;
mark_inode_dirty(inode);
unlock_super (sb);
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a980df858..b4f952d07 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -20,7 +20,6 @@
* (jj@sunsite.ms.mff.cuni.cz)
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/locks.h>
#include <linux/smp_lock.h>
@@ -43,7 +42,8 @@ void ext2_put_inode (struct inode * inode)
*/
void ext2_delete_inode (struct inode * inode)
{
- if (inode->i_ino == EXT2_ACL_IDX_INO ||
+ if (is_bad_inode(inode) ||
+ inode->i_ino == EXT2_ACL_IDX_INO ||
inode->i_ino == EXT2_ACL_DATA_INO)
return;
inode->u.ext2_i.i_dtime = CURRENT_TIME;
@@ -713,7 +713,9 @@ void ext2_read_inode (struct inode * inode)
else if (S_ISDIR(inode->i_mode))
inode->i_op = &ext2_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ext2_symlink_inode_operations;
+ inode->i_op = inode->i_blocks
+ ?&ext2_symlink_inode_operations
+ :&ext2_fast_symlink_inode_operations;
else
init_special_inode(inode, inode->i_mode,
le32_to_cpu(raw_inode->i_block[0]));
diff --git a/fs/ext2/ioctl.c b/fs/ext2/ioctl.c
index a582fd545..0b456820a 100644
--- a/fs/ext2/ioctl.c
+++ b/fs/ext2/ioctl.c
@@ -7,7 +7,6 @@
* Universite Pierre et Marie Curie (Paris VI)
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 8bc7532de..87f39796a 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -18,7 +18,6 @@
* for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/locks.h>
#include <linux/quotaops.h>
@@ -678,48 +677,32 @@ end_unlink:
int ext2_symlink (struct inode * dir, struct dentry *dentry, const char * symname)
{
- struct ext2_dir_entry_2 * de;
struct inode * inode;
- struct buffer_head * bh = NULL, * name_block = NULL;
- char * link;
- int i, l, err = -EIO;
- char c;
+ struct ext2_dir_entry_2 * de;
+ struct buffer_head * bh = NULL;
+ int l, err;
- if (!(inode = ext2_new_inode (dir, S_IFLNK, &err))) {
- return err;
- }
- inode->i_mode = S_IFLNK | S_IRWXUGO;
- inode->i_op = &ext2_symlink_inode_operations;
- for (l = 0; l < inode->i_sb->s_blocksize - 1 &&
- symname [l]; l++)
- ;
- if (l >= sizeof (inode->u.ext2_i.i_data)) {
-
- ext2_debug ("l=%d, normal symlink\n", l);
-
- name_block = ext2_bread (inode, 0, 1, &err);
- if (!name_block) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput (inode);
- return err;
- }
- link = name_block->b_data;
- } else {
- link = (char *) inode->u.ext2_i.i_data;
+ err = -ENAMETOOLONG;
+ l = strlen(symname)+1;
+ if (l > dir->i_sb->s_blocksize)
+ goto out;
- ext2_debug ("l=%d, fast symlink\n", l);
+ err = -EIO;
+ if (!(inode = ext2_new_inode (dir, S_IFLNK, &err)))
+ goto out;
+ inode->i_mode = S_IFLNK | S_IRWXUGO;
+
+ if (l > sizeof (inode->u.ext2_i.i_data)) {
+ inode->i_op = &ext2_symlink_inode_operations;
+ err = block_symlink(inode, symname, l);
+ if (err)
+ goto out_no_entry;
+ } else {
+ inode->i_op = &ext2_fast_symlink_inode_operations;
+ memcpy((char*)&inode->u.ext2_i.i_data,symname,l);
+ inode->i_size = l-1;
}
- i = 0;
- while (i < inode->i_sb->s_blocksize - 1 && (c = *(symname++)))
- link[i++] = c;
- link[i] = 0;
- if (name_block) {
- mark_buffer_dirty(name_block, 1);
- brelse (name_block);
- }
- inode->i_size = i;
mark_inode_dirty(inode);
bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
diff --git a/fs/ext2/symlink.c b/fs/ext2/symlink.c
index bf880e68a..18fbbb368 100644
--- a/fs/ext2/symlink.c
+++ b/fs/ext2/symlink.c
@@ -15,93 +15,29 @@
* ext2 symlink handling code
*/
-#include <linux/module.h>
#include <linux/fs.h>
-#include <asm/uaccess.h>
+#include <linux/ext2_fs.h>
-
-
-static int ext2_readlink (struct dentry *, char *, int);
-static struct dentry *ext2_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations ext2_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ext2_readlink, /* readlink */
- ext2_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static struct dentry * ext2_follow_link(struct dentry * dentry,
- struct dentry *base,
- unsigned int follow)
+static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- struct inode *inode = dentry->d_inode;
- struct buffer_head * bh = NULL;
- int error;
- char * link;
-
- link = (char *) inode->u.ext2_i.i_data;
- if (inode->i_blocks) {
- if (!(bh = ext2_bread (inode, 0, 0, &error))) {
- dput(base);
- return ERR_PTR(-EIO);
- }
- link = bh->b_data;
- }
- UPDATE_ATIME(inode);
- base = lookup_dentry(link, base, follow);
- if (bh)
- brelse(bh);
- return base;
+ char *s = (char *)dentry->d_inode->u.ext2_i.i_data;
+ return vfs_readlink(dentry, buffer, buflen, s);
}
-static int ext2_readlink (struct dentry * dentry, char * buffer, int buflen)
+static struct dentry *ext2_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
{
- struct inode *inode = dentry->d_inode;
- struct buffer_head * bh = NULL;
- char * link;
- int i;
-
- if (buflen > inode->i_sb->s_blocksize - 1)
- buflen = inode->i_sb->s_blocksize - 1;
+ char *s = (char *)dentry->d_inode->u.ext2_i.i_data;
+ return vfs_follow_link(dentry, base, flags, s);
+}
- link = (char *) inode->u.ext2_i.i_data;
- if (inode->i_blocks) {
- int err;
- bh = ext2_bread (inode, 0, 0, &err);
- if (!bh) {
- if(err < 0) /* indicate type of error */
- return err;
- return 0;
- }
- link = bh->b_data;
- }
+struct inode_operations ext2_fast_symlink_inode_operations = {
+ readlink: ext2_readlink,
+ follow_link: ext2_follow_link,
+};
- i = 0;
- while (i < buflen && link[i])
- i++;
- if (copy_to_user(buffer, link, i))
- i = -EFAULT;
- if (bh)
- brelse (bh);
- return i;
-}
+struct inode_operations ext2_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: ext2_get_block,
+ readpage: block_read_full_page,
+};
diff --git a/fs/ext2/truncate.c b/fs/ext2/truncate.c
index 653936278..ba8397196 100644
--- a/fs/ext2/truncate.c
+++ b/fs/ext2/truncate.c
@@ -18,7 +18,6 @@
* General cleanup and race fixes, wsh, 1998
*/
-#include <linux/module.h>
#include <linux/fs.h>
#include <linux/locks.h>
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 9c2c159cb..06da340fb 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -60,10 +60,8 @@ struct inode_operations fat_file_inode_operations = {
fat_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- block_flushpage, /* flushpage */
fat_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -113,39 +111,23 @@ static int fat_write_partial_page(struct file *file, struct page *page, unsigned
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
- struct page *new_page, **hash;
+ struct page *new_page;
unsigned long pgpos;
- struct page *page_cache = NULL;
long status;
- pgpos = MSDOS_I(inode)->i_realsize >> PAGE_CACHE_SHIFT;
- while (pgpos < page->index) {
- hash = page_hash(&inode->i_data, pgpos);
-repeat_find: new_page = __find_lock_page(&inode->i_data, pgpos, hash);
- if (!new_page) {
- if (!page_cache) {
- page_cache = page_cache_alloc();
- if (page_cache)
- goto repeat_find;
- status = -ENOMEM;
- goto out;
- }
- new_page = page_cache;
- if (add_to_page_cache_unique(new_page,&inode->i_data,pgpos,hash))
- goto repeat_find;
- page_cache = NULL;
- }
+ while((pgpos=MSDOS_I(inode)->i_realsize>>PAGE_CACHE_SHIFT)<page->index){
+ status = -ENOMEM;
+ new_page = grab_cache_page(&inode->i_data, pgpos);
+ if (!new_page)
+ goto out;
status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
UnlockPage(new_page);
page_cache_release(new_page);
if (status < 0)
goto out;
- pgpos = MSDOS_I(inode)->i_realsize >> PAGE_CACHE_SHIFT;
}
status = block_write_cont_page(file, page, offset, bytes, buf);
out:
- if (page_cache)
- page_cache_free(page_cache);
return status;
}
diff --git a/fs/fifo.c b/fs/fifo.c
index 757b2c4f4..516e690c9 100644
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -169,25 +169,6 @@ static struct file_operations def_fifo_fops = {
struct inode_operations fifo_inode_operations = {
&def_fifo_fops, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
diff --git a/fs/filesystems.c b/fs/filesystems.c
index da67d4d52..08d4aaf1b 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -31,6 +31,7 @@
#include <linux/hfs_fs.h>
#include <linux/devpts_fs.h>
#include <linux/bfs_fs.h>
+#include <linux/adfs_fs.h>
#include <linux/major.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
diff --git a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c
index a5ce908a7..602d85c52 100644
--- a/fs/hfs/dir_cap.c
+++ b/fs/hfs/dir_cap.c
@@ -90,10 +90,8 @@ struct inode_operations hfs_cap_ndir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -113,10 +111,8 @@ struct inode_operations hfs_cap_fdir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -136,10 +132,8 @@ struct inode_operations hfs_cap_rdir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c
index d68f7ed6a..bc32f23c1 100644
--- a/fs/hfs/dir_dbl.c
+++ b/fs/hfs/dir_dbl.c
@@ -89,10 +89,8 @@ struct inode_operations hfs_dbl_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c
index aa8a90220..855d3434e 100644
--- a/fs/hfs/dir_nat.c
+++ b/fs/hfs/dir_nat.c
@@ -96,10 +96,8 @@ struct inode_operations hfs_nat_ndir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -119,10 +117,8 @@ struct inode_operations hfs_nat_hdir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/hfs/file.c b/fs/hfs/file.c
index 594d65271..ec1d5ada4 100644
--- a/fs/hfs/file.c
+++ b/fs/hfs/file.c
@@ -66,10 +66,8 @@ struct inode_operations hfs_file_inode_operations = {
hfs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
hfs_file_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/hfs/file_cap.c b/fs/hfs/file_cap.c
index e96dd7f20..23566021b 100644
--- a/fs/hfs/file_cap.c
+++ b/fs/hfs/file_cap.c
@@ -80,10 +80,8 @@ struct inode_operations hfs_cap_info_inode_operations = {
NULL, /* get_block - none */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
cap_info_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidata */
};
diff --git a/fs/hfs/file_hdr.c b/fs/hfs/file_hdr.c
index 58a12133a..bb7d82e4f 100644
--- a/fs/hfs/file_hdr.c
+++ b/fs/hfs/file_hdr.c
@@ -82,10 +82,8 @@ struct inode_operations hfs_hdr_inode_operations = {
header part has no disk block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
hdr_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/hpfs/ea.c b/fs/hpfs/ea.c
index d7abdc991..9632c054c 100644
--- a/fs/hpfs/ea.c
+++ b/fs/hpfs/ea.c
@@ -69,8 +69,64 @@ static void set_indirect_ea(struct super_block *s, int ano, secno a, char *data,
hpfs_ea_write(s, a, ano, 0, size, data);
}
-/* Read an extended attribute named 'key' */
+/* Read an extended attribute named 'key' into the provided buffer */
+int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
+ char *buf, int size)
+{
+ unsigned pos;
+ int ano, len;
+ secno a;
+ struct extended_attribute *ea;
+ struct extended_attribute *ea_end = fnode_end_ea(fnode);
+ for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ memcpy(buf, ea_data(ea), ea->valuelen);
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ a = fnode->ea_secno;
+ len = fnode->ea_size_l;
+ ano = fnode->ea_anode;
+ pos = 0;
+ while (pos < len) {
+ char ex[4 + 255 + 1 + 8];
+ ea = (struct extended_attribute *)ex;
+ if (pos + 4 > len) {
+ hpfs_error(s, "EAs don't end correctly, %s %08x, len %08x",
+ ano ? "anode" : "sectors", a, len);
+ return -EIO;
+ }
+ if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
+ if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
+ return -EIO;
+ if (!strcmp(ea->name, key)) {
+ if (ea->indirect)
+ goto indirect;
+ if (ea->valuelen >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, a, ano, pos + 4 + ea->namelen + 1, ea->valuelen, buf))
+ return -EIO;
+ buf[ea->valuelen] = 0;
+ return 0;
+ }
+ pos += ea->namelen + ea->valuelen + 5;
+ }
+ return -ENOENT;
+indirect:
+ if (ea_len(ea) >= size)
+ return -EINVAL;
+ if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
+ return -EIO;
+ buf[ea_len(ea)] = 0;
+ return 0;
+}
+
+/* Read an extended attribute named 'key' */
char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *size)
{
char *ret;
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c
index 72f61c20a..8abaf2fd3 100644
--- a/fs/hpfs/file.c
+++ b/fs/hpfs/file.c
@@ -89,55 +89,25 @@ static int hpfs_write_partial_page(struct file *file, struct page *page, unsigne
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
- struct page *new_page, **hash;
+ struct page *new_page;
unsigned long pgpos;
- struct page * page_cache = NULL;
long status;
- printk("- off: %08x\n", (int)page->offset);
- pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK;
- while (pgpos < page->offset) {
-long pgp = pgpos;
- printk("pgpos: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks);
- hash = page_hash(&inode->i_data, pgpos);
-repeat_find: new_page = __find_lock_page(&inode->i_data, pgpos, hash);
- if (!new_page) {
- if (!page_cache) {
- page_cache = page_cache_alloc();
- if (page_cache)
- goto repeat_find;
- status = -ENOMEM;
- goto out;
- }
- new_page = page_cache;
- if (add_to_page_cache_unique(new_page,&inode->i_data,pgpos,hash))
- goto repeat_find;
- page_cache = NULL;
- }
- printk("A\n");
+ pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
+ while (pgpos < page->index) {
+ status = -ENOMEM;
+ new_page = grab_cache_page(&inode->i_data, pgpos);
+ if (!new_page)
+ goto out;
status = block_write_cont_page(file, new_page, PAGE_SIZE, 0, NULL);
- printk("B\n");
UnlockPage(new_page);
page_cache_release(new_page);
if (status < 0)
goto out;
- pgpos = (inode->i_blocks - 1) * 512 & PAGE_CACHE_MASK;
- printk("pgpos2: %08x, bl: %d\n", (int)pgpos, (int)inode->i_blocks);
- if (pgpos == pgp) {
- status = -1;
- printk("ERROR\n");
- goto out;
- }
+ pgpos = ((inode->i_blocks - 1) * 512) >> PAGE_CACHE_SHIFT;
}
- //if ((status = block_write_cont_page(file, page, PAGE_SIZE, 0, NULL)) < 0) goto out;
- printk("C\n");
status = block_write_cont_page(file, page, offset, bytes, buf);
- printk("D\n");
out:
- printk("O\n");
- if (page_cache)
- page_cache_free(page_cache);
- printk("E\n");
return status;
}
@@ -147,7 +117,7 @@ ssize_t hpfs_file_write(struct file *file, const char *buf, size_t count, loff_t
ssize_t retval;
retval = generic_file_write(file, buf, count,
- ppos, /*hpfs_write_partial_page*/block_write_partial_page);
+ ppos, hpfs_write_partial_page);
if (retval > 0) {
struct inode *inode = file->f_dentry->d_inode;
inode->i_mtime = CURRENT_TIME;
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 9ae4a67da..377b296e8 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -249,6 +249,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *, fnode_secno, struct f
/* ea.c */
void hpfs_ea_ext_remove(struct super_block *, secno, int, unsigned);
+int hpfs_read_ea(struct super_block *, struct fnode *, char *, char *, int);
char *hpfs_get_ea(struct super_block *, struct fnode *, char *, int *);
void hpfs_set_ea(struct inode *, struct fnode *, char *, char *, int);
@@ -283,10 +284,6 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_h
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);
dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino);
-/* mmap.c */
-
-int hpfs_mmap(struct file *, struct vm_area_struct *);
-
/* name.c */
unsigned char hpfs_upcase(unsigned char *, unsigned char);
@@ -305,8 +302,7 @@ int hpfs_mknod(struct inode *, struct dentry *, int, int);
int hpfs_symlink(struct inode *, struct dentry *, const char *);
int hpfs_unlink(struct inode *, struct dentry *);
int hpfs_rmdir(struct inode *, struct dentry *);
-int hpfs_readlink(struct dentry *, char *, int);
-struct dentry *hpfs_follow_link(struct dentry *, struct dentry *, unsigned int);
+int hpfs_symlink_readpage(struct dentry *, struct page *);
int hpfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/* super.c */
diff --git a/fs/hpfs/inode.c b/fs/hpfs/inode.c
index d79e55814..e4167bfdc 100644
--- a/fs/hpfs/inode.c
+++ b/fs/hpfs/inode.c
@@ -16,7 +16,7 @@ static const struct file_operations hpfs_file_ops =
NULL, /* readdir - bad */
NULL, /* poll - default */
NULL, /* ioctl - default */
- generic_file_mmap/*hpfs_mmap*/, /* mmap */
+ generic_file_mmap, /* mmap */
hpfs_open, /* open */
NULL, /* flush */
hpfs_file_release, /* release */
@@ -44,10 +44,8 @@ static const struct inode_operations hpfs_file_iops =
&hpfs_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
hpfs_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -87,38 +85,18 @@ static const struct inode_operations hpfs_dir_iops =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
const struct inode_operations hpfs_symlink_iops =
{
- NULL, /* default file operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- hpfs_readlink, /* readlink */
- hpfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: hpfs_symlink_readpage
};
-
void hpfs_read_inode(struct inode *i)
{
struct buffer_head *bh;
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index fe9b66e3d..85ce143db 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -396,54 +396,33 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
}
-int hpfs_readlink(struct dentry *dentry, char *buf, int len)
+int hpfs_symlink_readpage(struct dentry *dentry, struct page *page)
{
+ char *link = (char*)kmap(page);
struct inode *i = dentry->d_inode;
struct fnode *fnode;
struct buffer_head *bh;
- char *symlink;
- int slen;
- if (!S_ISLNK(i->i_mode)) {
- return -EINVAL;
- }
- if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
- return -EIO;
- }
- if (!(symlink = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &slen))) {
- brelse(bh);
- return -EFSERROR;
- }
- brelse(bh);
- if (slen > len) slen = len;
- memcpy_tofs(buf, symlink, slen);
- kfree(symlink);
- return slen;
-}
+ int err;
-struct dentry *hpfs_follow_link(struct dentry *dinode, struct dentry *ddir,
- unsigned int follow)
-{
- struct inode *inode = dinode->d_inode;
- char *link;
- unsigned len;
- struct buffer_head *bh;
- struct fnode *fnode;
- if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) {
- dput(dinode);
- return ERR_PTR(-EIO);
- }
- if (!(link = hpfs_get_ea(inode->i_sb, fnode, "SYMLINK", &len))) {
- brelse(bh);
- dput(dinode);
- return ERR_PTR(-EIO);
- }
+ err = -EIO;
+ if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
+ goto fail;
+ err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
brelse(bh);
- UPDATE_ATIME(inode);
- ddir = lookup_dentry(link, ddir, follow);
- kfree(link);
- return ddir;
-}
+ if (err)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
+}
+
int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
diff --git a/fs/inode.c b/fs/inode.c
index 811bf575d..0dcdf2a87 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -4,6 +4,7 @@
* (C) 1997 Linus Torvalds
*/
+#include <linux/config.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/mm.h>
@@ -756,3 +757,51 @@ void update_atime (struct inode *inode)
inode->i_atime = CURRENT_TIME;
mark_inode_dirty (inode);
} /* End Function update_atime */
+
+
+/*
+ * Quota functions that want to walk the inode lists..
+ */
+#ifdef CONFIG_QUOTA
+
+/* Functions back in dquot.c */
+void put_dquot_list(struct list_head *);
+int remove_inode_dquot_ref(struct inode *, short, struct list_head *);
+
+void remove_dquot_ref(kdev_t dev, short type)
+{
+ struct super_block *sb = get_super(dev);
+ struct inode *inode;
+ struct list_head *act_head;
+ LIST_HEAD(tofree_head);
+
+ if (!sb || !sb->dq_op)
+ return; /* nothing to do */
+
+ /* We have to be protected against other CPUs */
+ spin_lock(&inode_lock);
+
+ for (act_head = inode_in_use.next; act_head != &inode_in_use; act_head = act_head->next) {
+ inode = list_entry(act_head, struct inode, i_list);
+ if (inode->i_sb != sb || !IS_QUOTAINIT(inode))
+ continue;
+ remove_inode_dquot_ref(inode, type, &tofree_head);
+ }
+ for (act_head = inode_unused.next; act_head != &inode_unused; act_head = act_head->next) {
+ inode = list_entry(act_head, struct inode, i_list);
+ if (inode->i_sb != sb || !IS_QUOTAINIT(inode))
+ continue;
+ remove_inode_dquot_ref(inode, type, &tofree_head);
+ }
+ for (act_head = sb->s_dirty.next; act_head != &sb->s_dirty; act_head = act_head->next) {
+ inode = list_entry(act_head, struct inode, i_list);
+ if (!IS_QUOTAINIT(inode))
+ continue;
+ remove_inode_dquot_ref(inode, type, &tofree_head);
+ }
+ spin_unlock(&inode_lock);
+
+ put_dquot_list(&tofree_head);
+}
+
+#endif
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index bc64dfdd5..fb60d3a55 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -60,10 +60,8 @@ struct inode_operations isofs_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/isofs/file.c b/fs/isofs/file.c
index fd9b124ed..b15b6c5dc 100644
--- a/fs/isofs/file.c
+++ b/fs/isofs/file.c
@@ -51,9 +51,7 @@ struct inode_operations isofs_file_inode_operations = {
isofs_get_block, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index 8da9396cc..84aa2ec30 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -990,8 +990,8 @@ int isofs_get_block(struct inode *inode, long iblock,
}
bh_result->b_dev = inode->i_dev;
- bh_result->b_blocknr =
- (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode);
+ bh_result->b_blocknr = firstext +
+ ((b_off - offset) >> ISOFS_BUFFER_BITS(inode));
bh_result->b_state |= (1UL << BH_Mapped);
err = 0;
@@ -1236,8 +1236,7 @@ static void isofs_read_inode(struct inode * inode)
iso_date(raw_inode->date, high_sierra);
inode->u.isofs_i.i_first_extent = (isonum_733 (raw_inode->extent) +
- isonum_711 (raw_inode->ext_attr_length))
- << inode -> i_sb -> u.isofs_sb.s_log_zone_size;
+ isonum_711 (raw_inode->ext_attr_length));
/* Now test for possible Rock Ridge extensions which will override some of
these numbers in the inode structure. */
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 8b5c8befd..814d90b3c 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
#include "rock.h"
@@ -358,9 +359,10 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
#ifdef DEBUG
printk("RR CL (%x)\n",inode->i_ino);
#endif
- inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
- inode -> i_sb -> u.isofs_sb.s_log_zone_size;
- reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
+ inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location);
+ reloc = iget(inode->i_sb,
+ (inode->u.isofs_i.i_first_extent <<
+ inode -> i_sb -> u.isofs_sb.s_log_zone_size));
if (!reloc)
goto out;
inode->i_mode = reloc->i_mode;
@@ -386,142 +388,155 @@ int parse_rock_ridge_inode(struct iso_directory_record * de,
return 0;
}
+static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr)
+{
+ int slen;
+ int rootflag;
+ struct SL_component *oldslp;
+ struct SL_component *slp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ while (slen > 1) {
+ rootflag = 0;
+ switch (slp->flags & ~1) {
+ case 0:
+ memcpy(rpnt, slp->text, slp->len);
+ rpnt+=slp->len;
+ break;
+ case 4:
+ *rpnt++='.';
+ /* fallthru */
+ case 2:
+ *rpnt++='.';
+ break;
+ case 8:
+ rootflag = 1;
+ *rpnt++='/';
+ break;
+ default:
+ printk("Symlink component flag not implemented (%d)\n",
+ slp->flags);
+ }
+ slen -= slp->len + 2;
+ oldslp = slp;
+ slp = (struct SL_component *) ((char *) slp + slp->len + 2);
+
+ if (slen < 2) {
+ /*
+ * If there is another SL record, and this component
+ * record isn't continued, then add a slash.
+ */
+ if ((rr->u.SL.flags & 1) && !(oldslp->flags & 1))
+ *rpnt++='/';
+ break;
+ }
+
+ /*
+ * If this component record isn't continued, then append a '/'.
+ */
+ if (!rootflag && !(oldslp->flags & 1))
+ *rpnt++='/';
-/* Returns the name of the file that this inode is symlinked to. This is
- in malloc'd memory, so it needs to be freed, once we are through with it */
+ }
+ return rpnt;
+}
-char * get_rock_ridge_symlink(struct inode * inode)
-{
- unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
- unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
- struct buffer_head * bh;
- char * rpnt = NULL;
- unsigned char * pnt;
- struct iso_directory_record * raw_inode;
- CONTINUE_DECLS;
- int block;
- int sig;
- int rootflag;
- int len;
- unsigned char * chr;
- struct rock_ridge * rr;
-
- if (!inode->i_sb->u.isofs_sb.s_rock)
- panic("Cannot have symlink with high sierra variant of iso filesystem\n");
- block = inode->i_ino >> bufbits;
- bh = bread(inode->i_dev, block, bufsize);
- if (!bh)
- goto out_noread;
-
- pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
-
- raw_inode = ((struct iso_directory_record *) pnt);
-
- /*
- * If we go past the end of the buffer, there is some sort of error.
- */
- if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
- goto out_bad_span;
-
- /* Now test for possible Rock Ridge extensions which will override some of
- these numbers in the inode structure. */
-
- SETUP_ROCK_RIDGE(raw_inode, chr, len);
-
- repeat:
- while (len > 1){ /* There may be one byte for padding somewhere */
- rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
- sig = (chr[0] << 8) + chr[1];
- chr += rr->len;
- len -= rr->len;
-
- switch(sig){
- case SIG('R','R'):
- if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
- break;
- case SIG('S','P'):
- CHECK_SP(goto out);
- break;
- case SIG('S','L'):
- {int slen;
- struct SL_component * oldslp;
- struct SL_component * slp;
- slen = rr->len - 5;
- slp = &rr->u.SL.link;
- while (slen > 1){
- if (!rpnt){
- rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
- if (!rpnt) goto out;
- *rpnt = 0;
- };
- rootflag = 0;
- switch(slp->flags &~1){
- case 0:
- strncat(rpnt,slp->text, slp->len);
- break;
- case 2:
- strcat(rpnt,".");
- break;
- case 4:
- strcat(rpnt,"..");
- break;
- case 8:
- rootflag = 1;
- strcat(rpnt,"/");
- break;
- default:
- printk("Symlink component flag not implemented (%d)\n",slen);
- };
- slen -= slp->len + 2;
- oldslp = slp;
- slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
-
- if(slen < 2) {
- /*
- * If there is another SL record, and this component record
- * isn't continued, then add a slash.
- */
- if( ((rr->u.SL.flags & 1) != 0)
- && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
- break;
- }
+/* readpage() for symlinks: reads symlink contents into the page and either
+ makes it uptodate and returns 0 or returns error (-EIO) */
- /*
- * If this component record isn't continued, then append a '/'.
- */
- if( (!rootflag)
- && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
-
- };
- break;
- case SIG('C','E'):
- CHECK_CE; /* This tells is if there is a continuation record */
- break;
- default:
- break;
- }
- };
- };
- MAYBE_CONTINUE(repeat,inode);
-
-out_freebh:
+int rock_ridge_symlink_readpage(struct dentry *dentry, struct page *page)
+{
+ struct inode *inode = dentry->d_inode;
+ char *link = (char*)kmap(page);
+ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
+ unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
+ struct buffer_head *bh;
+ char *rpnt = link;
+ unsigned char *pnt;
+ struct iso_directory_record *raw_inode;
+ CONTINUE_DECLS;
+ int block;
+ int sig;
+ int len;
+ unsigned char *chr;
+ struct rock_ridge *rr;
+
+ if (!inode->i_sb->u.isofs_sb.s_rock)
+ panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
+
+ block = inode->i_ino >> bufbits;
+ bh = bread(inode->i_dev, block, bufsize);
+ if (!bh)
+ goto out_noread;
+
+ pnt = (unsigned char *) bh->b_data + (inode->i_ino & (bufsize - 1));
+
+ raw_inode = (struct iso_directory_record *) pnt;
+
+ /*
+ * If we go past the end of the buffer, there is some sort of error.
+ */
+ if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize)
+ goto out_bad_span;
+
+ /* Now test for possible Rock Ridge extensions which will override
+ some of these numbers in the inode structure. */
+
+ SETUP_ROCK_RIDGE(raw_inode, chr, len);
+
+ repeat:
+ while (len > 1) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *) chr;
+ if (rr->len == 0)
+ goto out; /* Something got screwed up here */
+ sig = (chr[0] << 8) + chr[1];
+ chr += rr->len;
+ len -= rr->len;
+
+ switch (sig) {
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] & RR_SL) == 0)
+ goto out;
+ break;
+ case SIG('S', 'P'):
+ CHECK_SP(goto out);
+ break;
+ case SIG('S', 'L'):
+ rpnt = get_symlink_chunk(rpnt, rr);
+ break;
+ case SIG('C', 'E'):
+ /* This tells is if there is a continuation record */
+ CHECK_CE;
+ default:
+ break;
+ }
+ }
+ MAYBE_CONTINUE(repeat, inode);
+
+ if (rpnt == link)
+ goto fail;
brelse(bh);
- return rpnt;
+ *rpnt = '\0';
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
/* error exit from macro */
-out:
- if(buffer)
+ out:
+ if (buffer)
kfree(buffer);
- if(rpnt)
- kfree(rpnt);
- rpnt = NULL;
- goto out_freebh;
-out_noread:
+ goto fail;
+ out_noread:
printk("unable to read i-node block");
- goto out_freebh;
-out_bad_span:
+ goto fail;
+ out_bad_span:
printk("symlink spans iso9660 blocks\n");
- goto out_freebh;
+ fail:
+ brelse(bh);
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
diff --git a/fs/isofs/symlink.c b/fs/isofs/symlink.c
index e5a7a2c72..219a4b9ac 100644
--- a/fs/isofs/symlink.c
+++ b/fs/isofs/symlink.c
@@ -17,72 +17,11 @@
#include <linux/stat.h>
#include <linux/malloc.h>
-#include <asm/uaccess.h>
-
-static int isofs_readlink(struct dentry *, char *, int);
-static struct dentry * isofs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
/*
* symlinks can't do much...
*/
struct inode_operations isofs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- isofs_readlink, /* readlink */
- isofs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: rock_ridge_symlink_readpage
};
-
-static int isofs_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- char * pnt;
- int i;
-
- if (buflen > 1023)
- buflen = 1023;
- pnt = get_rock_ridge_symlink(dentry->d_inode);
-
- if (!pnt)
- return 0;
-
- i = strlen(pnt);
- if (i > buflen)
- i = buflen;
- if (copy_to_user(buffer, pnt, i))
- i = -EFAULT;
- kfree(pnt);
- return i;
-}
-
-static struct dentry * isofs_follow_link(struct dentry * dentry,
- struct dentry *base,
- unsigned int follow)
-{
- char * pnt;
-
- pnt = get_rock_ridge_symlink(dentry->d_inode);
- if(!pnt) {
- dput(base);
- return ERR_PTR(-ELOOP);
- }
-
- base = lookup_dentry(pnt, base, follow);
-
- kfree(pnt);
- return base;
-}
diff --git a/fs/minix/dir.c b/fs/minix/dir.c
index a44d5d69d..52c0e0cee 100644
--- a/fs/minix/dir.c
+++ b/fs/minix/dir.c
@@ -55,10 +55,8 @@ struct inode_operations minix_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/minix/file.c b/fs/minix/file.c
index 6683c393c..4240f622e 100644
--- a/fs/minix/file.c
+++ b/fs/minix/file.c
@@ -73,9 +73,7 @@ struct inode_operations minix_file_inode_operations = {
minix_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
minix_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index b268a4676..a3e73dbcd 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -461,46 +461,43 @@ int minix_symlink(struct inode * dir, struct dentry *dentry,
{
struct minix_dir_entry * de;
struct inode * inode = NULL;
- struct buffer_head * bh = NULL, * name_block = NULL;
+ struct buffer_head * bh = NULL;
int i;
- char c;
-
- inode = minix_new_inode(dir, &i);
- if (i)
- return i;
+ int err;
+
+ err = -ENAMETOOLONG;
+ i = strlen(symname)+1;
+ if (i>1024)
+ goto out;
+ inode = minix_new_inode(dir, &err);
+ if (err)
+ goto out;
+ err = -ENOSPC;
if (!inode)
- return -ENOSPC;
+ goto out;
inode->i_mode = S_IFLNK | 0777;
inode->i_op = &minix_symlink_inode_operations;
- name_block = minix_bread(inode,0,1);
- if (!name_block) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- return -ENOSPC;
- }
- i = 0;
- while (i < 1023 && (c=*(symname++)))
- name_block->b_data[i++] = c;
- name_block->b_data[i] = 0;
- mark_buffer_dirty(name_block, 1);
- brelse(name_block);
- inode->i_size = i;
- mark_inode_dirty(inode);
- i = minix_add_entry(dir, dentry->d_name.name,
+ err = block_symlink(inode, symname, i);
+ if (err)
+ goto fail;
+
+ err = minix_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
- if (i) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- return i;
- }
+ if (err)
+ goto fail;
+
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
d_instantiate(dentry, inode);
- return 0;
+out:
+ return err;
+fail:
+ inode->i_nlink--;
+ mark_inode_dirty(inode);
+ iput(inode);
+ goto out;
}
int minix_link(struct dentry * old_dentry, struct inode * dir,
diff --git a/fs/minix/symlink.c b/fs/minix/symlink.c
index 3a8951b09..7e1d03a10 100644
--- a/fs/minix/symlink.c
+++ b/fs/minix/symlink.c
@@ -4,79 +4,19 @@
* Copyright (C) 1991, 1992 Linus Torvalds
*
* minix symlink handling code
+ *
+ * Code removed. 1999, AV ;-)
*/
-#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/minix_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-static int minix_readlink(struct dentry *, char *, int);
-static struct dentry *minix_follow_link(struct dentry *, struct dentry *, unsigned int);
/*
* symlinks can't do much...
*/
struct inode_operations minix_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- minix_readlink, /* readlink */
- minix_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: minix_get_block,
+ readpage: block_read_full_page
};
-
-static struct dentry * minix_follow_link(struct dentry * dentry,
- struct dentry * base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head * bh;
-
- bh = minix_bread(inode, 0, 0);
- if (!bh) {
- dput(base);
- return ERR_PTR(-EIO);
- }
- UPDATE_ATIME(inode);
- base = lookup_dentry(bh->b_data, base, follow);
- brelse(bh);
- return base;
-}
-
-static int minix_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct buffer_head * bh;
- int i;
- char c;
-
- if (buflen > 1023)
- buflen = 1023;
- bh = minix_bread(dentry->d_inode, 0, 0);
- if (!bh)
- return 0;
- i = 0;
- while (i<buflen && (c = bh->b_data[i])) {
- i++;
- put_user(c,buffer++);
- }
- brelse(bh);
- return i;
-}
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index d69aba48d..ea0b05616 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -600,10 +600,8 @@ struct inode_operations msdos_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
diff --git a/fs/namei.c b/fs/namei.c
index eba55a751..95ee1c127 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -16,6 +16,7 @@
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
+#include <linux/pagemap.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
@@ -283,7 +284,7 @@ static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry
if ((follow & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
- if (current->link_count < 5) {
+ if (current->link_count < 32) {
struct dentry * result;
current->link_count++;
@@ -1419,3 +1420,92 @@ asmlinkage long sys_rename(const char * oldname, const char * newname)
unlock_kernel();
return error;
}
+
+int vfs_readlink(struct dentry *dentry, char *buffer, int buflen, char *link)
+{
+ u32 len;
+
+ len = PTR_ERR(link);
+ if (IS_ERR(link))
+ goto out;
+
+ len = strlen(link);
+ if (len > buflen)
+ len = buflen;
+ copy_to_user(buffer, link, len);
+out:
+ return len;
+}
+
+static inline struct dentry *
+__vfs_follow_link(struct dentry *dentry, struct dentry *base,
+ unsigned follow, char *link)
+{
+ struct dentry *result;
+ UPDATE_ATIME(dentry->d_inode);
+
+ if (IS_ERR(link))
+ goto fail;
+
+ result = lookup_dentry(link, base, follow);
+ return result;
+
+fail:
+ dput(base);
+ return (struct dentry *)link;
+}
+
+struct dentry *
+vfs_follow_link(struct dentry *dentry, struct dentry *base,
+unsigned int follow, char *link)
+{
+ return __vfs_follow_link(dentry,base,follow,link);
+}
+
+/* get the link contents into pagecache */
+static char *page_getlink(struct dentry * dentry, struct page **ppage)
+{
+ struct page * page;
+ page = read_cache_page(&dentry->d_inode->i_data, 0,
+ (filler_t *)dentry->d_inode->i_op->readpage,
+ dentry);
+ if (IS_ERR(page))
+ goto sync_fail;
+ wait_on_page(page);
+ if (!Page_Uptodate(page))
+ goto async_fail;
+ *ppage = page;
+ return (char*) kmap(page);
+
+async_fail:
+ page_cache_release(page);
+ return ERR_PTR(-EIO);
+
+sync_fail:
+ return (char*)page;
+}
+
+int page_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ struct page *page = NULL;
+ char *s = page_getlink(dentry, &page);
+ int res = vfs_readlink(dentry,buffer,buflen,s);
+ if (page) {
+ kunmap(page);
+ page_cache_release(page);
+ }
+ return res;
+}
+
+struct dentry *
+page_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
+{
+ struct page *page = NULL;
+ char *s = page_getlink(dentry, &page);
+ struct dentry *res = __vfs_follow_link(dentry,base,follow,s);
+ if (page) {
+ kunmap(page);
+ page_cache_release(page);
+ }
+ return res;
+}
diff --git a/fs/ncpfs/Config.in b/fs/ncpfs/Config.in
index 5bbc29dc8..a9909cb49 100644
--- a/fs/ncpfs/Config.in
+++ b/fs/ncpfs/Config.in
@@ -6,10 +6,8 @@ bool ' Proprietary file locking' CONFIG_NCPFS_IOCTL_LOCKING
bool ' Clear remove/delete inhibit when needed' CONFIG_NCPFS_STRONG
bool ' Use NFS namespace if available' CONFIG_NCPFS_NFS_NS
bool ' Use LONG (OS/2) namespace if available' CONFIG_NCPFS_OS2_NS
-if [ "$CONFIG_NCPFS_OS2_NS" = "y" ]; then
- bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS
-fi
+bool ' Lowercase DOS filenames' CONFIG_NCPFS_SMALLDOS
bool ' Allow mounting of volume subdirectories' CONFIG_NCPFS_MOUNT_SUBDIR
-# bool ' NDS interserver authentication support' CONFIG_NCPFS_NDS_DOMAINS
+bool ' NDS authentication support' CONFIG_NCPFS_NDS_DOMAINS
bool ' Use Native Language Support' CONFIG_NCPFS_NLS
bool ' Enable symbolic links and execute flags' CONFIG_NCPFS_EXTRAS
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 4ed7a9abe..31e414ebb 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -4,7 +4,7 @@
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- * Modified 1998 Wolfram Pienkoss for NLS
+ * Modified 1998, 1999 Wolfram Pienkoss for NLS
* Modified 1999 Wolfram Pienkoss for directory caching
*
*/
@@ -81,10 +81,8 @@ struct inode_operations ncp_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -112,25 +110,23 @@ struct dentry_operations ncp_dentry_operations =
/*
- * XXX: It would be better to use the tolower from linux/ctype.h,
- * but _ctype is needed and it is not exported.
- */
-#define tolower(c) (((c) >= 'A' && (c) <= 'Z') ? (c)-('A'-'a') : (c))
-
-/*
* Note: leave the hash unchanged if the directory
* is case-sensitive.
*/
static int
ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
{
+ struct nls_table *t;
unsigned long hash;
int i;
+ t = NCP_IO_TABLE(dentry);
+
if (!ncp_case_sensitive(dentry->d_inode)) {
hash = init_name_hash();
for (i=0; i<this->len ; i++)
- hash = partial_name_hash(tolower(this->name[i]),hash);
+ hash = partial_name_hash(ncp_tolower(t, this->name[i]),
+ hash);
this->hash = end_name_hash(hash);
}
return 0;
@@ -139,18 +135,13 @@ ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
static int
ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
{
- int i;
-
- if (a->len != b->len) return 1;
+ if (a->len != b->len)
+ return 1;
if (ncp_case_sensitive(dentry->d_inode))
- return strncmp(a->name, b->name, a->len);
-
- for (i=0; i<a->len; i++)
- if (tolower(a->name[i]) != tolower(b->name[i]))
- return 1;
+ return strncmp(a->name, b->name, a->len);
- return 0;
+ return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
}
/*
@@ -303,10 +294,9 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
{
struct ncp_server *server;
struct inode *dir = dentry->d_parent->d_inode;
- int res, val = 0;
- int len = dentry->d_name.len;
struct ncp_entry_info finfo;
- __u8 __name[dentry->d_name.len + 1];
+ int res, val = 0, len = dentry->d_name.len + 1;
+ __u8 __name[len];
if (!dentry->d_inode || !dir)
goto finished;
@@ -326,79 +316,42 @@ ncp_lookup_validate(struct dentry * dentry, int flags)
if (val)
goto finished;
- PPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld\n",
+ DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
NCP_GET_AGE(dentry));
- memcpy(__name, dentry->d_name.name, len);
- __name[len] = '\0';
-
- PPRINTK("ncp_lookup_validate: %s, len %d\n", __name, len);
- PPRINTK("ncp_lookup_validate: server lookup for %s/%s\n",
- dentry->d_parent->d_name.name, __name);
-
if (ncp_is_server_root(dir)) {
- io2vol(server, __name, 1);
- res = ncp_lookup_volume(server, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, 1);
+ if (!res)
+ res = ncp_lookup_volume(server, __name, &(finfo.i));
} else {
- io2vol(server, __name, !ncp_preserve_case(dir));
- res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (!res)
+ res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
- PPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
+ DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
dentry->d_parent->d_name.name, __name, res);
/*
* If we didn't find it, or if it has a different dirEntNum to
* what we remember, it's not valid any more.
*/
if (!res) {
- if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum)
+ if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
+ ncp_new_dentry(dentry);
val=1;
- else
- PPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
+ } else
+ DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
- vol2io(server, finfo.i.entryName,
- !ncp_preserve_entry_case(dir, finfo.i.NSCreator));
ncp_update_inode2(dentry->d_inode, &finfo);
- if (val)
- ncp_new_dentry(dentry);
}
finished:
- PPRINTK("ncp_lookup_validate: result=%d\n", val);
+ DDPRINTK("ncp_lookup_validate: result=%d\n", val);
return val;
}
-static struct page *
-ncp_get_cache_page(struct inode *inode, unsigned long offset, int used)
-{
- struct address_space *i_data = &inode->i_data;
- struct page *new_page, *page, **hash;
-
- hash = page_hash(i_data, offset);
-
- page = __find_lock_page(i_data, offset, hash);
- if (used || page)
- return page;
-
- new_page = page_cache_alloc();
- if (!new_page)
- return NULL;
-
- for (;;) {
- page = new_page;
- if (!add_to_page_cache_unique(page, i_data, offset, hash))
- break;
- page_cache_release(page);
- page = __find_lock_page(i_data, offset, hash);
- if (page) {
- page_cache_free(new_page);
- break;
- }
- }
-
- return page;
-}
-
/* most parts from nfsd_d_validate() */
static int
ncp_d_validate(struct dentry *dentry)
@@ -458,11 +411,12 @@ ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
goto out;
next = next->next;
}
- dent = NULL;
+ return NULL;
+
out:
- if (dent)
- if (dent->d_inode)
- return dget(dent);
+ if (dent->d_inode)
+ return dget(dent);
+
return NULL;
}
@@ -472,8 +426,7 @@ static time_t ncp_obtain_mtime(struct dentry *dentry)
struct ncp_server *server = NCP_SERVER(inode);
struct nw_info_struct i;
- if (!ncp_conn_valid(server) ||
- ncp_is_server_root(inode))
+ if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
return 0;
if (ncp_obtain_info(server, inode, NULL, &i))
@@ -518,11 +471,11 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
filp->f_pos = 2;
}
- page = ncp_get_cache_page(inode, 0, 0);
+ page = grab_cache_page(&inode->i_data, 0);
if (!page)
goto read_really;
- ctl.cache = cache = (union ncp_dir_cache *) page_address(page);
+ ctl.cache = cache = (union ncp_dir_cache *) kmap(page);
ctl.head = cache->head;
if (!Page_Uptodate(page) || !ctl.head.eof)
@@ -547,13 +500,12 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
for (;;) {
if (ctl.ofs != 0) {
- ctl.page = ncp_get_cache_page(inode, ctl.ofs, 1);
+ ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
if (!ctl.page)
goto invalid_cache;
+ ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
if (!Page_Uptodate(ctl.page))
goto invalid_cache;
- ctl.cache = (union ncp_dir_cache *)
- page_address(ctl.page);
}
while (ctl.idx < NCP_DIRCACHE_SIZE) {
struct dentry *dent;
@@ -575,6 +527,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto finished;
}
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -585,6 +538,7 @@ static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
invalid_cache:
if (ctl.page) {
+ kunmap(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
ctl.page = NULL;
@@ -615,11 +569,13 @@ read_really:
finished:
if (page) {
cache->head = ctl.head;
+ kunmap(page);
SetPageUptodate(page);
UnlockPage(page);
page_cache_release(page);
}
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -634,17 +590,19 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
{
struct dentry *newdent, *dentry = filp->f_dentry;
struct inode *newino, *inode = dentry->d_inode;
- struct ncp_server *server = NCP_SERVER(inode);
struct ncp_cache_control ctl = *ctrl;
struct qstr qname;
- ino_t ino = 0;
int valid = 0;
+ ino_t ino = 0;
+ __u8 __name[256];
- vol2io(server, entry->i.entryName,
- !ncp_preserve_entry_case(inode, entry->i.NSCreator));
+ qname.len = 256;
+ if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
+ entry->i.entryName, entry->i.nameLen,
+ !ncp_preserve_entry_case(inode, entry->i.NSCreator)))
+ return 1; /* I'm not sure */
- qname.name = entry->i.entryName;
- qname.len = entry->i.nameLen;
+ qname.name = __name;
qname.hash = full_name_hash(qname.name, qname.len);
if (dentry->d_op && dentry->d_op->d_hash)
@@ -680,6 +638,7 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
if (ctl.idx >= NCP_DIRCACHE_SIZE) {
if (ctl.page) {
+ kunmap(ctl.page);
SetPageUptodate(ctl.page);
UnlockPage(ctl.page);
page_cache_release(ctl.page);
@@ -687,10 +646,9 @@ ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
ctl.cache = NULL;
ctl.idx -= NCP_DIRCACHE_SIZE;
ctl.ofs += 1;
- ctl.page = ncp_get_cache_page(inode, ctl.ofs, 0);
+ ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
if (ctl.page)
- ctl.cache = (union ncp_dir_cache *)
- page_address(ctl.page);
+ ctl.cache = (union ncp_dir_cache *) kmap(ctl.page);
}
if (ctl.cache) {
ctl.cache->dentry[ctl.idx] = newdent;
@@ -705,8 +663,8 @@ end_advance:
ino = find_inode_number(dentry, &qname);
if (!ino)
ino = iunique(inode->i_sb, 2);
- ctl.filled = filldir(dirent, entry->i.entryName,
- entry->i.nameLen, filp->f_pos, ino);
+ ctl.filled = filldir(dirent, qname.name, qname.len,
+ filp->f_pos, ino);
if (!ctl.filled)
filp->f_pos += 1;
}
@@ -751,8 +709,9 @@ ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
}
}
-static void ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
- struct ncp_cache_control *ctl)
+static void
+ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
+ struct ncp_cache_control *ctl)
{
struct dentry *dentry = filp->f_dentry;
struct inode *dir = dentry->d_inode;
@@ -788,19 +747,21 @@ int ncp_conn_logged_in(struct super_block *sb)
{
struct ncp_server* server = NCP_SBP(sb);
struct nw_info_struct i;
- int result;
+ int result, len = strlen(server->m.mounted_vol) + 1;
+ __u8 __name[len];
if (ncp_single_volume(server)) {
struct dentry* dent;
result = -ENOENT;
- io2vol(server, server->m.mounted_vol, 1);
- if (ncp_lookup_volume(server, server->m.mounted_vol, &i)) {
+ if (ncp_io2vol(server, __name, &len, server->m.mounted_vol,
+ len-1, 1))
+ goto out;
+ if (ncp_lookup_volume(server, __name, &i)) {
PPRINTK("ncp_conn_logged_in: %s not found\n",
server->m.mounted_vol);
goto out;
}
- vol2io(server, i.entryName, 1);
dent = sb->s_root;
if (dent) {
struct inode* ino = dent->d_inode;
@@ -823,29 +784,29 @@ out:
static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
{
- struct ncp_server *server;
+ struct ncp_server *server = NCP_SERVER(dir);
struct inode *inode = NULL;
- int error, res, len = dentry->d_name.len;
struct ncp_entry_info finfo;
- __u8 __name[dentry->d_name.len + 1];
-
- server = NCP_SERVER(dir);
+ int error, res, len = dentry->d_name.len + 1;
+ __u8 __name[len];
error = -EIO;
if (!ncp_conn_valid(server))
goto finished;
- memcpy(__name, dentry->d_name.name, len);
- __name[len] = '\0';
- PPRINTK("ncp_lookup: %s, len %d\n", __name, len);
PPRINTK("ncp_lookup: server lookup for %s/%s\n",
- dentry->d_parent->d_name.name, __name);
+ dentry->d_parent->d_name.name, dentry->d_name.name);
+
if (ncp_is_server_root(dir)) {
- io2vol(server, __name, 1);
- res = ncp_lookup_volume(server, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, 1);
+ if (!res)
+ res = ncp_lookup_volume(server, __name, &(finfo.i));
} else {
- io2vol(server, __name, !ncp_preserve_case(dir));
- res = ncp_obtain_info(server, dir, __name, &(finfo.i));
+ res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (!res)
+ res = ncp_obtain_info(server, dir, __name, &(finfo.i));
}
PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
dentry->d_parent->d_name.name, __name, res);
@@ -855,9 +816,6 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
if (res)
goto add_entry;
- vol2io(server, finfo.i.entryName,
- !ncp_preserve_entry_case(dir, finfo.i.NSCreator));
-
/*
* Create an inode for the entry.
*/
@@ -867,10 +825,10 @@ static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
inode = ncp_iget(dir->i_sb, &finfo);
if (inode) {
+ ncp_new_dentry(dentry);
add_entry:
dentry->d_op = &ncp_dentry_operations;
d_add(dentry, inode);
- ncp_new_dentry(dentry);
error = 0;
}
@@ -907,10 +865,10 @@ out_close:
int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
int attributes)
{
- int error, result;
- struct ncp_entry_info finfo;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ struct ncp_entry_info finfo;
+ int error, result, len = dentry->d_name.len + 1;
+ __u8 __name[len];
PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
dentry->d_parent->d_name.name, dentry->d_name.name, mode);
@@ -919,16 +877,15 @@ int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
goto out;
ncp_age_dentry(server, dentry);
-
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
-
- io2vol(server, _name, !ncp_preserve_case(dir));
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
error = -EACCES;
- result = ncp_open_create_file_or_subdir(server, dir, _name,
- OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
- attributes, AR_READ | AR_WRITE, &finfo);
+ result = ncp_open_create_file_or_subdir(server, dir, __name,
+ OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
+ attributes, AR_READ | AR_WRITE, &finfo);
if (!result) {
finfo.access = O_RDWR;
error = ncp_instantiate(dir, dentry, &finfo);
@@ -949,10 +906,10 @@ static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- int error;
struct ncp_entry_info finfo;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ int error, len = dentry->d_name.len + 1;
+ __u8 __name[len];
DPRINTK("ncp_mkdir: making %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -961,13 +918,13 @@ static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
goto out;
ncp_age_dentry(server, dentry);
-
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
- io2vol(server, _name, !ncp_preserve_case(dir));
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
error = -EACCES;
- if (ncp_open_create_file_or_subdir(server, dir, _name,
+ if (ncp_open_create_file_or_subdir(server, dir, __name,
OC_MODE_CREATE, aDIR, 0xffff,
&finfo) == 0)
{
@@ -979,9 +936,9 @@ out:
static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
{
- int error, result;
struct ncp_server *server = NCP_SERVER(dir);
- __u8 _name[dentry->d_name.len + 1];
+ int error, result, len = dentry->d_name.len + 1;
+ __u8 __name[len];
DPRINTK("ncp_rmdir: removing %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -994,11 +951,12 @@ static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
if (!list_empty(&dentry->d_hash))
goto out;
- memcpy(_name, dentry->d_name.name, dentry->d_name.len);
- _name[dentry->d_name.len] = '\0';
-
- io2vol(server, _name, !ncp_preserve_case(dir));
- result = ncp_del_file_or_subdir(server, dir, _name);
+ error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
+ len-1, !ncp_preserve_case(dir));
+ if (error)
+ goto out;
+
+ result = ncp_del_file_or_subdir(server, dir, __name);
switch (result) {
case 0x00:
error = 0;
@@ -1091,38 +1049,42 @@ out:
static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry)
{
- int old_len = old_dentry->d_name.len;
- int new_len = new_dentry->d_name.len;
+ struct ncp_server *server = NCP_SERVER(old_dir);
int error;
- char _old_name[old_dentry->d_name.len + 1];
- char _new_name[new_dentry->d_name.len + 1];
+ int old_len = old_dentry->d_name.len + 1;
+ int new_len = new_dentry->d_name.len + 1;
+ __u8 __old_name[old_len], __new_name[new_len];
DPRINTK("ncp_rename: %s/%s to %s/%s\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
error = -EIO;
- if (!ncp_conn_valid(NCP_SERVER(old_dir)))
+ if (!ncp_conn_valid(server))
goto out;
- ncp_age_dentry(NCP_SERVER(old_dir), old_dentry);
- ncp_age_dentry(NCP_SERVER(new_dir), new_dentry);
+ ncp_age_dentry(server, old_dentry);
+ ncp_age_dentry(server, new_dentry);
- memcpy(_old_name, old_dentry->d_name.name, old_len);
- _old_name[old_len] = '\0';
- io2vol(NCP_SERVER(old_dir), _old_name, !ncp_preserve_case(old_dir));
+ error = ncp_io2vol(server, __old_name, &old_len,
+ old_dentry->d_name.name, old_len-1,
+ !ncp_preserve_case(old_dir));
+ if (error)
+ goto out;
- memcpy(_new_name, new_dentry->d_name.name, new_len);
- _new_name[new_len] = '\0';
- io2vol(NCP_SERVER(new_dir), _new_name, !ncp_preserve_case(new_dir));
+ error = ncp_io2vol(server, __new_name, &new_len,
+ new_dentry->d_name.name, new_len-1,
+ !ncp_preserve_case(new_dir));
+ if (error)
+ goto out;
- error = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
- old_dir, _old_name,
- new_dir, _new_name);
+ error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
+ new_dir, __new_name);
#ifdef CONFIG_NCPFS_STRONG
- if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
- error = ncp_force_rename(old_dir, old_dentry, _old_name,
- new_dir, new_dentry, _new_name);
+ if ((error == 0x90 || error == -EACCES) &&
+ server->m.flags & NCP_MOUNT_STRONG) { /* RO */
+ error = ncp_force_rename(old_dir, old_dentry, __old_name,
+ new_dir, new_dentry, __new_name);
}
#endif
switch (error) {
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c
index 4a907a9b1..98fd9f23e 100644
--- a/fs/ncpfs/file.c
+++ b/fs/ncpfs/file.c
@@ -294,9 +294,7 @@ struct inode_operations ncp_file_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
index ec2c1a4e4..26bd474d2 100644
--- a/fs/ncpfs/inode.c
+++ b/fs/ncpfs/inode.c
@@ -124,16 +124,15 @@ void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
}
inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
- inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.modifyTime),
- le16_to_cpu(nwinfo->i.modifyDate));
- inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwinfo->i.creationTime),
- le16_to_cpu(nwinfo->i.creationDate));
- inode->i_atime = ncp_date_dos2unix(0,
- le16_to_cpu(nwinfo->i.lastAccessDate));
+ inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
+ le16_to_cpu(nwi->modifyDate));
+ inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
+ le16_to_cpu(nwi->creationDate));
+ inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate));
- NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
- NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
- NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
+ NCP_FINFO(inode)->DosDirNum = nwi->DosDirNum;
+ NCP_FINFO(inode)->dirEntNum = nwi->dirEntNum;
+ NCP_FINFO(inode)->volNumber = nwi->volNumber;
}
/*
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 05def9d6c..36063db81 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- * Modified 1998 Wolfram Pienkoss for NLS
+ * Modified 1998, 1999 Wolfram Pienkoss for NLS
*
*/
@@ -364,8 +364,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_NDS_DOMAINS
case NCP_IOC_GETOBJECTNAME:
- if ( (permission(inode, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (current->uid != server->m.mounted_uid) {
return -EACCES;
}
{
@@ -396,8 +395,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
}
case NCP_IOC_SETOBJECTNAME:
- if ( (permission(inode, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (current->uid != server->m.mounted_uid) {
return -EACCES;
}
{
@@ -441,8 +439,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
}
case NCP_IOC_GETPRIVATEDATA:
- if ( (permission(inode, MAY_READ) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (current->uid != server->m.mounted_uid) {
return -EACCES;
}
{
@@ -471,8 +468,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
}
case NCP_IOC_SETPRIVATEDATA:
- if ( (permission(inode, MAY_WRITE) != 0)
- && (current->uid != server->m.mounted_uid)) {
+ if (current->uid != server->m.mounted_uid) {
return -EACCES;
}
{
@@ -531,7 +527,8 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
codepage = NULL;
user.codepage[NCP_IOCSNAME_LEN] = 0;
- if (!user.codepage[0])
+ if (!user.codepage[0] ||
+ !strcmp(user.codepage, "default"))
codepage = load_nls_default();
else {
codepage = load_nls(user.codepage);
@@ -542,13 +539,21 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
iocharset = NULL;
user.iocharset[NCP_IOCSNAME_LEN] = 0;
- if (user.iocharset[0] == 0)
+ if (!user.iocharset[0] ||
+ !strcmp(user.iocharset, "default")) {
iocharset = load_nls_default();
- else {
- iocharset = load_nls(user.iocharset);
- if (!iocharset) {
- unload_nls(codepage);
- return -EBADRQC;
+ NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
+ } else {
+ if (!strcmp(user.iocharset, "utf8")) {
+ iocharset = load_nls_default();
+ NCP_SET_FLAG(server, NCP_FLAG_UTF8);
+ } else {
+ iocharset = load_nls(user.iocharset);
+ if (!iocharset) {
+ unload_nls(codepage);
+ return -EBADRQC;
+ }
+ NCP_CLR_FLAG(server, NCP_FLAG_UTF8);
}
}
@@ -568,35 +573,28 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
case NCP_IOC_GETCHARSETS: /* not tested */
{
struct ncp_nls_ioctl user;
+ int len;
memset(&user, 0, sizeof(user));
- if (server->nls_vol)
- if (server->nls_vol->charset) {
- strncpy(user.codepage,
- server->nls_vol->charset,
- NCP_IOCSNAME_LEN);
- user.codepage[NCP_IOCSNAME_LEN] = 0;
- if (!strcmp(user.codepage, "default"))
- /* unfortunately, we cannot set
- 'default' charset... maybe
- we should change load_nls()?
- It is easy, do not initialize
- 'tables' in fs/nls/nls_base.c
- with NULL, but with
- 'default_table'... */
- memset(user.codepage, 0,
- sizeof(user.codepage));
- }
+ if (server->nls_vol && server->nls_vol->charset) {
+ len = strlen(server->nls_vol->charset);
+ if (len > NCP_IOCSNAME_LEN)
+ len = NCP_IOCSNAME_LEN;
+ strncpy(user.codepage,
+ server->nls_vol->charset, len);
+ user.codepage[len] = 0;
+ }
- if (server->nls_io)
- if (server->nls_io->charset) {
+ if (NCP_IS_FLAG(server, NCP_FLAG_UTF8))
+ strcpy(user.iocharset, "utf8");
+ else
+ if (server->nls_io && server->nls_io->charset) {
+ len = strlen(server->nls_io->charset);
+ if (len > NCP_IOCSNAME_LEN)
+ len = NCP_IOCSNAME_LEN;
strncpy(user.iocharset,
- server->nls_io->charset,
- NCP_IOCSNAME_LEN);
- user.iocharset[NCP_IOCSNAME_LEN] = 0;
- if (!strcmp(user.iocharset, "default"))
- memset(user.iocharset, 0,
- sizeof(user.iocharset));
+ server->nls_io->charset, len);
+ user.iocharset[len] = 0;
}
if (copy_to_user((struct ncp_nls_ioctl*)arg, &user,
diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
index 036e92e93..806c05d6e 100644
--- a/fs/ncpfs/mmap.c
+++ b/fs/ncpfs/mmap.c
@@ -43,10 +43,11 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
int bufsize;
int pos;
- page = alloc_page(GFP_KERNEL);
+ page = alloc_page(GFP_HIGHMEM); /* ncpfs has nothing against GFP_HIGHMEM
+ as long as recvmsg and memset works on it */
if (!page)
return page;
- pg_addr = page_address(page);
+ pg_addr = kmap(page);
address &= PAGE_MASK;
pos = address - area->vm_start + (area->vm_pgoff << PAGE_SHIFT);
@@ -87,6 +88,7 @@ static struct page* ncp_file_mmap_nopage(struct vm_area_struct *area,
if (already_read < PAGE_SIZE)
memset((char*)(pg_addr + already_read), 0,
PAGE_SIZE - already_read);
+ kunmap(page);
return page;
}
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index 5dbd0c55a..7220e4852 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -4,6 +4,7 @@
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
+ * Modified 1999 Wolfram Pienkoss for NLS
*
*/
@@ -886,4 +887,225 @@ ncp_ClearPhysicalRecord(struct ncp_server *server, const char *file_id,
}
#endif /* CONFIG_NCPFS_IOCTL_LOCKING */
+#ifdef CONFIG_NCPFS_NLS
+/* This are the NLS conversion routines with inspirations and code parts
+ * from the vfat file system and hints from Petr Vandrovec.
+ */
+
+inline unsigned char
+ncp__tolower(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2lower[c];
+
+ return nc ? nc : c;
+}
+
+inline unsigned char
+ncp__toupper(struct nls_table *t, unsigned char c)
+{
+ unsigned char nc = t->charset2upper[c];
+
+ return nc ? nc : c;
+}
+
+int
+ncp__io2vol(struct ncp_server *server, unsigned char *vname, unsigned int *vlen,
+ const unsigned char *iname, unsigned int ilen, int cc)
+{
+ struct nls_table *in = server->nls_io;
+ struct nls_table *out = server->nls_vol;
+ struct nls_unicode uc;
+ unsigned char nc, *up;
+ int i, k, maxlen = *vlen - 1;
+ __u16 ec;
+
+ *vlen = 0;
+
+ for (i = 0; i < ilen;) {
+ if (*vlen == maxlen)
+ return -ENAMETOOLONG;
+
+ if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+ k = utf8_mbtowc(&ec, iname, ilen - i);
+ if (k == -1)
+ return -EINVAL;
+ uc.uni1 = ec & 0xFF;
+ uc.uni2 = ec >> 8;
+ iname += k;
+ i += k;
+ } else {
+ if (*iname == NCP_ESC) {
+ if (i > ilen - 5)
+ return -EINVAL;
+
+ ec = 0;
+ for (k = 1; k < 5; k++) {
+ nc = iname[k];
+ ec <<= 4;
+ if (nc >= '0' && nc <= '9') {
+ ec |= nc - '0';
+ continue;
+ }
+ if (nc >= 'a' && nc <= 'f') {
+ ec |= nc - ('a' - 10);
+ continue;
+ }
+ if (nc >= 'A' && nc <= 'F') {
+ ec |= nc - ('A' - 10);
+ continue;
+ }
+ return -EINVAL;
+ }
+ uc.uni1 = ec & 0xFF;
+ uc.uni2 = ec >> 8;
+ iname += 5;
+ i += 5;
+ } else {
+ uc = in->charset2uni[*iname];
+ iname++;
+ i++;
+ }
+ }
+
+ up = out->page_uni2charset[uc.uni2];
+ if (!up)
+ return -EINVAL;
+
+ nc = up[uc.uni1];
+ if (!nc)
+ return -EINVAL;
+
+ *vname = cc ? ncp_toupper(out, nc) : nc;
+ vname++;
+ *vlen += 1;
+ }
+
+ *vname = 0;
+ return 0;
+}
+
+int
+ncp__vol2io(struct ncp_server *server, unsigned char *iname, unsigned int *ilen,
+ const unsigned char *vname, unsigned int vlen, int cc)
+{
+ struct nls_table *in = server->nls_vol;
+ struct nls_table *out = server->nls_io;
+ struct nls_unicode uc;
+ unsigned char nc, *up;
+ int i, k, maxlen = *ilen - 1;
+ __u16 ec;
+
+ *ilen = 0;
+
+ for (i = 0; i < vlen; i++) {
+ if (*ilen == maxlen)
+ return -ENAMETOOLONG;
+
+ uc = in->charset2uni[cc ? ncp_tolower(in, *vname) : *vname];
+
+ if (NCP_IS_FLAG(server, NCP_FLAG_UTF8)) {
+ k = utf8_wctomb(iname, (uc.uni2 << 8) + uc.uni1,
+ maxlen - *ilen);
+ if (k == -1)
+ return -ENAMETOOLONG;
+ iname += k;
+ *ilen += k;
+ } else {
+ up = out->page_uni2charset[uc.uni2];
+ if (up)
+ nc = up[uc.uni1];
+ else
+ nc = 0;
+
+ if (nc) {
+ *iname = nc;
+ iname++;
+ *ilen += 1;
+ } else {
+ if (*ilen > maxlen - 5)
+ return -ENAMETOOLONG;
+ ec = (uc.uni2 << 8) + uc.uni1;
+ *iname = NCP_ESC;
+ for (k = 4; k > 0; k--) {
+ nc = ec & 0xF;
+ iname[k] = nc > 9 ? nc + ('a' - 10)
+ : nc + '0';
+ ec >>= 4;
+ }
+ iname += 5;
+ *ilen += 5;
+ }
+ }
+ vname++;
+ }
+
+ *iname = 0;
+ return 0;
+}
+#else
+
+int
+ncp__io2vol(unsigned char *vname, unsigned int *vlen,
+ const unsigned char *iname, unsigned int ilen, int cc)
+{
+ int i;
+
+ if (*vlen <= ilen)
+ return -ENAMETOOLONG;
+
+ if (cc)
+ for (i = 0; i < ilen; i++) {
+ *vname = toupper(*iname);
+ vname++;
+ iname++;
+ }
+ else {
+ memmove(vname, iname, ilen);
+ vname += ilen;
+ }
+
+ *vlen = ilen;
+ *vname = 0;
+ return 0;
+}
+
+int
+ncp__vol2io(unsigned char *iname, unsigned int *ilen,
+ const unsigned char *vname, unsigned int vlen, int cc)
+{
+ int i;
+
+ if (*ilen <= vlen)
+ return -ENAMETOOLONG;
+
+ if (cc)
+ for (i = 0; i < vlen; i++) {
+ *iname = tolower(*vname);
+ iname++;
+ vname++;
+ }
+ else {
+ memmove(iname, vname, vlen);
+ iname += vlen;
+ }
+
+ *ilen = vlen;
+ *iname = 0;
+ return 0;
+}
+
+#endif
+
+inline int
+ncp_strnicmp(struct nls_table *t, const unsigned char *s1,
+ const unsigned char *s2, int n)
+{
+ int i;
+
+ for (i=0; i<n; i++)
+ if (ncp_tolower(t, s1[i]) != ncp_tolower(t, s2[i]))
+ return 1;
+
+ return 0;
+}
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 92309db26..8b33a5c2e 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -4,7 +4,7 @@
* Copyright (C) 1995, 1996 by Volker Lendecke
* Modified for big endian by J.F. Chadima and David S. Miller
* Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
- * Modified 1998 Wolfram Pienkoss for NLS
+ * Modified 1998, 1999 Wolfram Pienkoss for NLS
* Modified 1999 Wolfram Pienkoss for directory caching
*
*/
@@ -29,7 +29,9 @@
#ifdef CONFIG_NCPFS_NLS
#include <linux/nls.h>
-#endif
+#else
+#include <linux/ctype.h>
+#endif /* CONFIG_NCPFS_NLS */
#include <linux/ncp_fs.h>
@@ -97,82 +99,40 @@ ncp_mount_subdir(struct ncp_server *, struct nw_info_struct *,
#endif /* CONFIG_NCPFS_MOUNT_SUBDIR */
#ifdef CONFIG_NCPFS_NLS
-/* This are the NLS conversion routines with inspirations and code parts
- * from the vfat file system and hints from Petr Vandrovec.
- */
-/*
- * It should be replaced by charset specifc conversion. Gordon Chaffee
- * has prepared some things, but I don't know, what he thinks about it.
- * The conversion tables for the io charsets should be generatable by
- * Unicode table, shouldn't it? I have written so generation code for it.
- * The tables for the vendor specific codepages...? Hmm. The Samba sources
- * contains also any hints.
- */
+inline unsigned char ncp__tolower(struct nls_table *, unsigned char);
+inline unsigned char ncp__toupper(struct nls_table *, unsigned char);
+int ncp__io2vol(struct ncp_server *, unsigned char *, unsigned int *,
+ const unsigned char *, unsigned int, int);
+int ncp__vol2io(struct ncp_server *, unsigned char *, unsigned int *,
+ const unsigned char *, unsigned int, int);
-#define toupperif(c, u) ((((u) != 0) && ((c) >= 'a') && ((c) <= 'z')) \
- ? (c)-('a'-'A') : (c))
-#define tolowerif(c, u) ((((u) != 0) && ((c) >= 'A') && ((c) <= 'Z')) \
- ? (c)-('A'-'a') : (c))
-
-static inline void
-io2vol(struct ncp_server *server, char *name, int case_trans)
-{
- unsigned char nc;
- unsigned char *np;
- unsigned char *up;
- struct nls_unicode uc;
- struct nls_table *nls_in;
- struct nls_table *nls_out;
-
- nls_in = server->nls_io;
- nls_out = server->nls_vol;
- np = name;
-
- while (*np)
- {
- nc = 0;
- uc = nls_in->charset2uni[toupperif(*np, case_trans)];
- up = nls_out->page_uni2charset[uc.uni2];
- if (up != NULL) nc = up[uc.uni1];
- if (nc != 0) *np = nc;
- np++;
- }
-}
-
-static inline void
-vol2io(struct ncp_server *server, char *name, int case_trans)
-{
- unsigned char nc;
- unsigned char *np;
- unsigned char *up;
- struct nls_unicode uc;
- struct nls_table *nls_in;
- struct nls_table *nls_out;
-
- nls_in = server->nls_vol;
- nls_out = server->nls_io;
- np = name;
-
- while (*np)
- {
- nc = 0;
- uc = nls_in->charset2uni[*np];
- up = nls_out->page_uni2charset[uc.uni2];
- if (up != NULL) nc = up[uc.uni1];
- if (nc == 0) nc = *np;
- *np = tolowerif(nc, case_trans);
- np++;
- }
-}
+#define NCP_ESC ':'
+#define NCP_IO_TABLE(dentry) (NCP_SERVER((dentry)->d_inode)->nls_io)
+#define ncp_tolower(t, c) ncp__tolower(t, c)
+#define ncp_toupper(t, c) ncp__toupper(t, c)
+#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(S,m,i,n,k,U)
+#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(S,m,i,n,k,U)
#else
-#define io2vol(S,N,U) if (U) str_upper(N)
-#define vol2io(S,N,U) if (U) str_lower(N)
+int ncp__io2vol(unsigned char *, unsigned int *,
+ const unsigned char *, unsigned int, int);
+int ncp__vol2io(unsigned char *, unsigned int *,
+ const unsigned char *, unsigned int, int);
+
+#define NCP_IO_TABLE(dentry) NULL
+#define ncp_tolower(t, c) tolower(c)
+#define ncp_toupper(t, c) toupper(c)
+#define ncp_io2vol(S,m,i,n,k,U) ncp__io2vol(m,i,n,k,U)
+#define ncp_vol2io(S,m,i,n,k,U) ncp__vol2io(m,i,n,k,U)
#endif /* CONFIG_NCPFS_NLS */
+inline int
+ncp_strnicmp(struct nls_table *,
+ const unsigned char *, const unsigned char *, int);
+
#define NCP_GET_AGE(dentry) (jiffies - (dentry)->d_time)
#define NCP_MAX_AGE(server) ((server)->dentry_ttl)
#define NCP_TEST_AGE(server,dentry) (NCP_GET_AGE(dentry) < NCP_MAX_AGE(server))
diff --git a/fs/ncpfs/symlink.c b/fs/ncpfs/symlink.c
index 81151959a..5e5bf2fbd 100644
--- a/fs/ncpfs/symlink.c
+++ b/fs/ncpfs/symlink.c
@@ -38,139 +38,76 @@
#define NCP_SYMLINK_MAGIC0 le32_to_cpu(0x6c6d7973) /* "symlnk->" */
#define NCP_SYMLINK_MAGIC1 le32_to_cpu(0x3e2d6b6e)
-static int ncp_readlink(struct dentry *, char *, int);
-static struct dentry *ncp_follow_link(struct dentry *, struct dentry *, unsigned int);
int ncp_create_new(struct inode *dir, struct dentry *dentry,
int mode,int attributes);
-/*
- * symlinks can't do much...
- */
-struct inode_operations ncp_symlink_inode_operations={
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ncp_readlink, /* readlink */
- ncp_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-/* ----- follow a symbolic link ------------------------------------------ */
+/* ----- read a symbolic link ------------------------------------------ */
-static struct dentry *ncp_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
+static int ncp_symlink_readpage(struct dentry *dentry, struct page *page)
{
struct inode *inode=dentry->d_inode;
- int error, length, cnt;
+ int error, length, len, cnt;
char *link;
+ char *buf = (char*)kmap(page);
-#ifdef DEBUG
- PRINTK("ncp_follow_link(dentry=%p,base=%p,follow=%u)\n",dentry,base,follow);
-#endif
-
- if(!S_ISLNK(inode->i_mode)) {
- dput(base);
- return ERR_PTR(-EINVAL);
- }
+ error = -EIO;
+ if (ncp_make_open(inode,O_RDONLY))
+ goto fail;
- if(ncp_make_open(inode,O_RDONLY)) {
- dput(base);
- return ERR_PTR(-EIO);
- }
-
- for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1, GFP_NFS))==NULL; cnt++) {
- if (cnt > 10) {
- dput(base);
- return ERR_PTR(-EAGAIN); /* -ENOMEM? */
- }
+ error = -ENOMEM;
+ for (cnt = 0; (link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE, GFP_NFS))==NULL; cnt++) {
+ if (cnt > 10)
+ goto fail;
schedule();
}
error=ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
0,NCP_MAX_SYMLINK_SIZE,link,&length);
- if (error!=0 || length<NCP_MIN_SYMLINK_SIZE ||
- ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 || ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
- dput(base);
+ if (error) {
kfree(link);
- return ERR_PTR(-EIO);
+ goto fail;
}
-
- link[length]=0;
-
- vol2io(NCP_SERVER(inode), link+8, 0);
-
- /* UPDATE_ATIME(inode); */
- base=lookup_dentry(link+8, base, follow);
- kfree(link);
-
- return base;
-}
-
-/* ----- read symbolic link ---------------------------------------------- */
-
-static int ncp_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode=dentry->d_inode;
- char *link;
- int length,error;
-
-#ifdef DEBUG
- PRINTK("ncp_readlink(dentry=%p,buffer=%p,buflen=%d)\n",dentry,buffer,buflen);
-#endif
-
- if(!S_ISLNK(inode->i_mode))
- return -EINVAL;
-
- if(ncp_make_open(inode,O_RDONLY))
- return -EIO;
-
- if((link=(char *)kmalloc(NCP_MAX_SYMLINK_SIZE+1,GFP_NFS))==NULL)
- return -ENOMEM;
-
- error = ncp_read_kernel(NCP_SERVER(inode),NCP_FINFO(inode)->file_handle,
- 0,NCP_MAX_SYMLINK_SIZE,link,&length);
-
- if (error!=0 || length < NCP_MIN_SYMLINK_SIZE || buflen < (length-8) ||
- ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
- error = -EIO;
- goto out;
+ if (length<NCP_MIN_SYMLINK_SIZE ||
+ ((__u32 *)link)[0]!=NCP_SYMLINK_MAGIC0 ||
+ ((__u32 *)link)[1]!=NCP_SYMLINK_MAGIC1) {
+ error = -EIO;
+ kfree(link);
+ goto fail;
}
- link[length] = 0;
-
- vol2io(NCP_SERVER(inode), link+8, 0);
-
- error = length - 8;
- if(copy_to_user(buffer, link+8, error))
- error = -EFAULT;
-
-out:;
+ len = NCP_MAX_SYMLINK_SIZE;
+ error = ncp_vol2io(NCP_SERVER(inode), buf, &len, link+8, length-8, 0);
kfree(link);
+ if (error)
+ goto fail;
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
return error;
}
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations ncp_symlink_inode_operations={
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: ncp_symlink_readpage,
+};
+
/* ----- create a new symbolic link -------------------------------------- */
int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
- int i,length;
struct inode *inode;
char *link;
+ int length, err, i;
#ifdef DEBUG
PRINTK("ncp_symlink(dir=%p,dentry=%p,symname=%s)\n",dir,dentry,symname);
@@ -179,7 +116,7 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
if (!(NCP_SERVER(dir)->m.flags & NCP_MOUNT_SYMLINKS))
return -EPERM; /* EPERM is returned by VFS if symlink procedure does not exist */
- if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE)
+ if ((length=strlen(symname))>NCP_MAX_SYMLINK_SIZE-8)
return -EINVAL;
if ((link=(char *)kmalloc(length+9,GFP_NFS))==NULL)
@@ -194,12 +131,16 @@ int ncp_symlink(struct inode *dir, struct dentry *dentry, const char *symname) {
((__u32 *)link)[0]=NCP_SYMLINK_MAGIC0;
((__u32 *)link)[1]=NCP_SYMLINK_MAGIC1;
- memcpy(link+8, symname, length+1); /* including last zero for io2vol */
/* map to/from server charset, do not touch upper/lower case as
symlink can point out of ncp filesystem */
- io2vol(NCP_SERVER(inode), link+8, 0);
-
+ length += 1;
+ err = ncp_io2vol(NCP_SERVER(inode),link+8,&length,symname,length-1,0);
+ if (err) {
+ kfree(link);
+ return err;
+ }
+
if(ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
0, length+8, link, &i) || i!=length+8) {
kfree(link);
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 149077fae..788307cc2 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -81,10 +81,8 @@ struct inode_operations nfs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
nfs_revalidate, /* revalidate */
};
@@ -302,77 +300,80 @@ out_error:
* page-in of the RPC reply, nowhere else, this simplies
* things substantially.
*/
-static struct page *try_to_get_dirent_page(struct file *file, __u32 cookie, int refetch_ok)
+
+static int nfs_dir_filler(struct dentry *dentry, struct page *page)
{
struct nfs_readdirargs rd_args;
struct nfs_readdirres rd_res;
- struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
- struct page *page, **hash, *page_cache;
- long offset;
+ long offset = page->index;
__u32 *cookiep;
+ int err;
- page = NULL;
- page_cache = page_cache_alloc();
- if (!page_cache)
- goto out;
-
- if ((offset = nfs_readdir_offset(inode, cookie)) < 0) {
- if (!refetch_ok ||
- (offset = refetch_to_readdir_cookie(file, inode)) < 0) {
- page_cache_free(page_cache);
- goto out;
- }
- }
+ kmap(page);
+ err = -EIO;
cookiep = find_cookie(inode, offset);
- if (!cookiep) {
- /* Gross fatal error. */
- page_cache_free(page_cache);
- goto out;
- }
-
- hash = page_hash(&inode->i_data, offset);
-repeat:
- page = __find_lock_page(&inode->i_data, offset, hash);
- if (page) {
- page_cache_free(page_cache);
- goto unlock_out;
- }
-
- page = page_cache;
- if (add_to_page_cache_unique(page, &inode->i_data, offset, hash)) {
- page_cache_release(page);
- goto repeat;
- }
+ if (!cookiep)
+ goto fail;
rd_args.fh = NFS_FH(dentry);
- rd_res.buffer = (char *)page_address(page_cache);
+ rd_res.buffer = (char *)page_address(page);
rd_res.bufsiz = PAGE_CACHE_SIZE;
rd_res.cookie = *cookiep;
do {
rd_args.buffer = rd_res.buffer;
rd_args.bufsiz = rd_res.bufsiz;
rd_args.cookie = rd_res.cookie;
- if (rpc_call(NFS_CLIENT(inode),
- NFSPROC_READDIR, &rd_args, &rd_res, 0) < 0)
- goto error;
+ err = rpc_call(NFS_CLIENT(inode),
+ NFSPROC_READDIR, &rd_args, &rd_res, 0);
+ if (err < 0)
+ goto fail;
} while(rd_res.bufsiz > 0);
+ err = -EIO;
if (rd_res.bufsiz < 0)
NFS_DIREOF(inode) = rd_res.cookie;
else if (create_cookie(rd_res.cookie, offset, inode))
- goto error;
+ goto fail;
SetPageUptodate(page);
-unlock_out:
+ kunmap(page);
UnlockPage(page);
-out:
+ return 0;
+fail:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return err;
+}
+
+static struct page *try_to_get_dirent_page(struct file *file, __u32 cookie, int refetch_ok)
+{
+ struct dentry *dentry = file->f_dentry;
+ struct inode *inode = dentry->d_inode;
+ struct page *page;
+ long offset;
+
+ if ((offset = nfs_readdir_offset(inode, cookie)) < 0) {
+ if (!refetch_ok ||
+ (offset = refetch_to_readdir_cookie(file, inode)) < 0) {
+ goto fail;
+ }
+ }
+
+ page = read_cache_page(&inode->i_data, offset,
+ (filler_t *)nfs_dir_filler, dentry);
+ if (IS_ERR(page))
+ goto fail;
+ if (!Page_Uptodate(page))
+ goto fail2;
return page;
-error:
- SetPageError(page);
- goto unlock_out;
+fail2:
+ page_cache_release(page);
+fail:
+ return NULL;
}
/* Seek up to dirent assosciated with the passed in cookie,
@@ -417,7 +418,7 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_dentry;
struct inode *inode = dentry->d_inode;
- struct page *page, **hash;
+ struct page *page;
long offset;
int res;
@@ -431,15 +432,16 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
if ((offset = nfs_readdir_offset(inode, filp->f_pos)) < 0)
goto no_dirent_page;
- hash = page_hash(&inode->i_data, offset);
- page = __find_get_page(&inode->i_data, offset, hash);
+ page = find_get_page(&inode->i_data, offset);
if (!page)
goto no_dirent_page;
if (!Page_Uptodate(page))
goto dirent_read_error;
success:
+ kmap(page);
filp->f_pos = nfs_do_filldir((__u32 *) page_address(page),
filp->f_pos, dirent, filldir);
+ kunmap(page);
page_cache_release(page);
return 0;
@@ -681,6 +683,7 @@ struct dentry_operations nfs_dentry_operations = {
NULL /* d_iput */
};
+#if 0 /* dead code */
#ifdef NFS_PARANOIA
/*
* Display all dentries holding the specified inode.
@@ -702,7 +705,8 @@ static void show_dentry(struct list_head * dlist)
unhashed);
}
}
-#endif
+#endif /* NFS_PARANOIA */
+#endif /* 0 */
static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
{
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index ab9b22683..00279fc6a 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -74,10 +74,8 @@ struct inode_operations nfs_file_inode_operations = {
NULL, /* get_block */
nfs_readpage, /* readpage */
nfs_writepage, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
nfs_revalidate, /* revalidate */
};
@@ -171,7 +169,8 @@ static int nfs_write_one_page(struct file *file, struct page *page, unsigned lon
{
long status;
- bytes -= copy_from_user((u8*)page_address(page) + offset, buf, bytes);
+ bytes -= copy_from_user((u8*)kmap(page) + offset, buf, bytes);
+ kunmap(page);
status = -EFAULT;
if (bytes) {
lock_kernel();
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 00b310e06..abf7f16f9 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -958,8 +958,6 @@ init_nfs_fs(void)
return err;
#ifdef CONFIG_PROC_FS
- rpc_register_sysctl();
- rpc_proc_init();
rpc_proc_register(&nfs_rpcstat);
#endif
return register_filesystem(&nfs_fs_type);
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 6b2e3d73a..37a8715cf 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -71,7 +71,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
{
struct nfs_rreq rqst;
unsigned long offset = page->index << PAGE_CACHE_SHIFT;
- char *buffer = (char *) page_address(page);
+ char *buffer;
int rsize = NFS_SERVER(inode)->rsize;
int result, refresh = 0;
int count = PAGE_SIZE;
@@ -79,6 +79,12 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
dprintk("NFS: nfs_readpage_sync(%p)\n", page);
+ /*
+ * This works now because the socket layer never tries to DMA
+ * into this buffer directly.
+ */
+ buffer = (char *) kmap(page);
+
do {
if (count < rsize)
rsize = count;
@@ -116,6 +122,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
result = 0;
io_error:
+ kunmap(page);
UnlockPage(page);
/* Note: we don't refresh if the call returned error */
if (refresh && result >= 0)
@@ -152,6 +159,7 @@ nfs_readpage_result(struct rpc_task *task)
fail++;
dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
}
+ kunmap(page);
UnlockPage(page);
free_page(address);
@@ -163,7 +171,7 @@ static inline int
nfs_readpage_async(struct dentry *dentry, struct inode *inode,
struct page *page)
{
- unsigned long address = page_address(page);
+ unsigned long address;
struct nfs_rreq *req;
int result = -1, flags;
@@ -177,6 +185,7 @@ nfs_readpage_async(struct dentry *dentry, struct inode *inode,
if (!req)
goto out_defer;
+ address = kmap(page);
/* Initialize request */
/* N.B. Will the dentry remain valid for life of request? */
nfs_readreq_setup(req, NFS_FH(dentry), page->index << PAGE_CACHE_SHIFT,
@@ -200,6 +209,7 @@ out_defer:
goto out;
out_free:
dprintk("NFS: failed to enqueue async READ request.\n");
+ kunmap(page);
kfree(req);
goto out;
}
@@ -217,9 +227,8 @@ out_free:
* - The server is congested.
*/
int
-nfs_readpage(struct file *file, struct page *page)
+nfs_readpage(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
int error;
@@ -254,7 +263,7 @@ nfs_readpage(struct file *file, struct page *page)
out_error:
UnlockPage(page);
out_free:
- free_page(page_address(page));
+ __free_page(page);
out:
unlock_kernel();
return error;
diff --git a/fs/nfs/symlink.c b/fs/nfs/symlink.c
index 1b1705ef2..ab0ebf145 100644
--- a/fs/nfs/symlink.c
+++ b/fs/nfs/symlink.c
@@ -22,145 +22,86 @@
#include <linux/malloc.h>
#include <linux/string.h>
-#include <asm/uaccess.h>
-
-static int nfs_readlink(struct dentry *, char *, int);
-static struct dentry *nfs_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations nfs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- nfs_readlink, /* readlink */
- nfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
/* Symlink caching in the page cache is even more simplistic
* and straight-forward than readdir caching.
*/
-static struct page *try_to_get_symlink_page(struct dentry *dentry, struct inode *inode)
+static int nfs_symlink_filler(struct dentry *dentry, struct page *page)
{
struct nfs_readlinkargs rl_args;
- struct page *page, **hash, *page_cache;
-
- page = NULL;
- page_cache = page_cache_alloc();
- if (!page_cache)
- goto out;
-
- hash = page_hash(&inode->i_data, 0);
-repeat:
- page = __find_lock_page(&inode->i_data, 0, hash);
- if (page) {
- page_cache_free(page_cache);
- goto unlock_out;
- }
-
- page = page_cache;
- if (add_to_page_cache_unique(page, &inode->i_data, 0, hash)) {
- page_cache_release(page);
- goto repeat;
- }
-
+ kmap(page);
/* We place the length at the beginning of the page,
* in host byte order, followed by the string. The
* XDR response verification will NULL terminate it.
*/
rl_args.fh = NFS_FH(dentry);
- rl_args.buffer = (const void *)page_address(page_cache);
- if (rpc_call(NFS_CLIENT(inode), NFSPROC_READLINK,
+ rl_args.buffer = (const void *)page_address(page);
+ if (rpc_call(NFS_CLIENT(dentry->d_inode), NFSPROC_READLINK,
&rl_args, NULL, 0) < 0)
goto error;
SetPageUptodate(page);
-unlock_out:
+ kunmap(page);
UnlockPage(page);
-out:
- return page;
+ return 0;
error:
SetPageError(page);
- goto unlock_out;
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
-static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+static char *nfs_getlink(struct dentry *dentry, struct page **ppage)
{
struct inode *inode = dentry->d_inode;
struct page *page;
- u32 *p, len;
+ u32 *p;
/* Caller revalidated the directory inode already. */
- page = find_get_page(&inode->i_data, 0);
- if (!page)
- goto no_readlink_page;
+ page = read_cache_page(&inode->i_data, 0,
+ (filler_t *)nfs_symlink_filler, dentry);
+ if (IS_ERR(page))
+ goto read_failed;
if (!Page_Uptodate(page))
- goto readlink_read_error;
-success:
- p = (u32 *) page_address(page);
- len = *p++;
- if (len > buflen)
- len = buflen;
- copy_to_user(buffer, p, len);
+ goto getlink_read_error;
+ *ppage = page;
+ p = (u32 *) kmap(page);
+ return (char*)(p+1);
+
+getlink_read_error:
page_cache_release(page);
- return len;
+ return ERR_PTR(-EIO);
+read_failed:
+ return (char*)page;
+}
-no_readlink_page:
- page = try_to_get_symlink_page(dentry, inode);
- if (!page)
- goto no_page;
- if (Page_Uptodate(page))
- goto success;
-readlink_read_error:
- page_cache_release(page);
-no_page:
- return -EIO;
+static int nfs_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ struct page *page = NULL;
+ int res = vfs_readlink(dentry,buffer,buflen,nfs_getlink(dentry,&page));
+ if (page) {
+ kunmap(page);
+ page_cache_release(page);
+ }
+ return res;
}
static struct dentry *
nfs_follow_link(struct dentry *dentry, struct dentry *base, unsigned int follow)
{
- struct dentry *result;
- struct inode *inode = dentry->d_inode;
- struct page *page;
- u32 *p;
-
- /* Caller revalidated the directory inode already. */
- page = find_get_page(&inode->i_data, 0);
- if (!page)
- goto no_followlink_page;
- if (!Page_Uptodate(page))
- goto followlink_read_error;
-success:
- p = (u32 *) page_address(page);
- result = lookup_dentry((char *) (p + 1), base, follow);
- page_cache_release(page);
- return result;
-
-no_followlink_page:
- page = try_to_get_symlink_page(dentry, inode);
- if (!page)
- goto no_page;
- if (Page_Uptodate(page))
- goto success;
-followlink_read_error:
- page_cache_release(page);
-no_page:
- return ERR_PTR(-EIO);
+ struct page *page = NULL;
+ struct dentry *res = vfs_follow_link(dentry, base, follow,
+ nfs_getlink(dentry, &page));
+ if (page) {
+ kunmap(page);
+ page_cache_release(page);
+ }
+ return res;
}
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations nfs_symlink_inode_operations = {
+ readlink: nfs_readlink,
+ follow_link: nfs_follow_link,
+};
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index abc048dc2..9f58b4171 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -99,7 +99,7 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
dentry->d_parent->d_name.name, dentry->d_name.name,
count, page->index, offset);
- buffer = (u8 *) page_address(page) + offset;
+ buffer = (u8 *) kmap(page) + offset;
offset += page->index << PAGE_CACHE_SHIFT;
do {
@@ -132,6 +132,7 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
} while (count);
io_error:
+ kunmap(page);
/* Note: we don't refresh if the call failed (fattr invalid) */
if (refresh && result >= 0) {
/* See comments in nfs_wback_result */
@@ -314,6 +315,7 @@ create_write_request(struct file * file, struct page *page, unsigned int offset,
wreq->wb_bytes = bytes;
wreq->wb_count = 2; /* One for the IO, one for us */
+ kmap(page);
append_write_request(&NFS_WRITEBACK(inode), wreq);
if (nr_write_requests++ > NFS_WRITEBACK_MAX*3/4)
@@ -412,9 +414,8 @@ wait_on_write_request(struct nfs_wreq *req)
* (for now), and we currently do this synchronously only.
*/
int
-nfs_writepage(struct file * file, struct page *page)
+nfs_writepage(struct dentry * dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
return nfs_writepage_sync(dentry, dentry->d_inode, page, 0, PAGE_SIZE);
}
@@ -687,6 +688,7 @@ nfs_wback_result(struct rpc_task *task)
if (WB_INVALIDATE(req))
ClearPageUptodate(page);
+ kunmap(page);
__free_page(page);
remove_write_request(&NFS_WRITEBACK(inode), req);
nr_write_requests--;
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index 4d8025650..152a8b0b2 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -11,6 +11,9 @@ O_TARGET := nfsd.o
O_OBJS := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
export.o auth.o lockd.o nfscache.o nfsxdr.o \
stats.o
+ifdef CONFIG_NFSD_V3
+ O_OBJS += nfs3proc.o nfs3xdr.o
+endif
M_OBJS := $(O_TARGET)
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index d5b1537db..14b55c450 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -105,20 +105,6 @@ out:
return exp;
}
-/*
- * Check whether there are any exports for a device.
- */
-static int
-exp_device_in_use(kdev_t dev)
-{
- struct svc_client *clp;
-
- for (clp = clients; clp; clp = clp->cl_next) {
- if (exp_find(clp, dev))
- return 1;
- }
- return 0;
-}
/*
* Look up the device of the parent fs.
@@ -286,6 +272,12 @@ exp_export(struct nfsctl_export *nxp)
goto finish;
err = -EINVAL;
+ if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) ||
+ inode->i_sb->s_op->read_inode == NULL) {
+ dprintk("exp_export: export of invalid fs type.\n");
+ goto finish;
+ }
+
if ((parent = exp_child(clp, dev, dentry)) != NULL) {
dprintk("exp_export: export not valid (Rule 3).\n");
goto finish;
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 5396a784f..3b0de5545 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -3,7 +3,7 @@
*
* Process version 3 NFS requests.
*
- * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/linkage.h>
@@ -18,19 +18,32 @@
#include <linux/version.h>
#include <linux/unistd.h>
#include <linux/malloc.h>
+#include <linux/major.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
#include <linux/nfsd/cache.h>
#include <linux/nfsd/xdr3.h>
-
-typedef struct svc_rqst svc_rqst;
-typedef struct svc_buf svc_buf;
+#include <linux/nfs3.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
#define RETURN(st) { resp->status = (st); return (st); }
+static int nfs3_ftypes[] = {
+ 0, /* NF3NON */
+ S_IFREG, /* NF3REG */
+ S_IFDIR, /* NF3DIR */
+ S_IFBLK, /* NF3BLK */
+ S_IFCHR, /* NF3CHR */
+ S_IFLNK, /* NF3LNK */
+ S_IFSOCK, /* NF3SOCK */
+ S_IFIFO, /* NF3FIFO */
+};
+
+/*
+ * Reserve room in the send buffer
+ */
static void
svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
{
@@ -38,6 +51,9 @@ svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
*len = buf->buflen - buf->len - nr;
}
+/*
+ * NULL call.
+ */
static int
nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
{
@@ -46,7 +62,6 @@ nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
/*
* Get a file's attributes
- * N.B. After this call resp->fh needs an fh_put
*/
static int
nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
@@ -54,18 +69,17 @@ nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
{
int nfserr;
- dprintk("nfsd: GETATTR %x/%ld\n",
+ dprintk("nfsd: GETATTR(3) %x/%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh));
+ (long)SVCFH_INO(&argp->fh));
- resp->fh = argp->fh;
+ fh_copy(&resp->fh, &argp->fh);
nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
RETURN(nfserr);
}
/*
* Set a file's attributes
- * N.B. After this call resp->fh needs an fh_put
*/
static int
nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
@@ -73,31 +87,30 @@ nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp,
{
int nfserr;
- dprintk("nfsd: SETATTR %x/%ld\n",
+ dprintk("nfsd: SETATTR(3) %x/%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh));
+ (long)SVCFH_INO(&argp->fh));
- resp->fh = argp->fh;
+ fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
RETURN(nfserr);
}
/*
* Look up a path name component
- * N.B. After this call _both_ resp->dirfh and resp->fh need an fh_put
*/
static int
nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
- struct nfsd3_lookupres *resp)
+ struct nfsd3_diropres *resp)
{
int nfserr;
- dprintk("nfsd: LOOKUP %x/%ld %s\n",
+ dprintk("nfsd: LOOKUP(3) %x/%ld %s\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
argp->name);
- resp->dirfh = argp->fh;
+ fh_copy(&resp->dirfh, &argp->fh);
nfserr = nfsd_lookup(rqstp, &resp->dirfh,
argp->name,
argp->len,
@@ -109,12 +122,20 @@ nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
* Check file access
*/
static int
-nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
+nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
struct nfsd3_accessres *resp)
{
- /* to be done */
- resp->fh = argp->fh;
- return nfserr_notsupp;
+ int nfserr;
+
+ dprintk("nfsd: ACCESS(3) %x/%ld 0x%x\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
+ argp->access);
+
+ fh_copy(&resp->fh, &argp->fh);
+ resp->access = argp->access;
+ nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
+ RETURN(nfserr);
}
/*
@@ -127,23 +148,23 @@ nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd_fhandle *argp,
u32 *path;
int dummy, nfserr;
- dprintk("nfsd: READLINK %x/%ld\n",
+ dprintk("nfsd: READLINK(3) %x/%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh));
+ (long)SVCFH_INO(&argp->fh));
/* Reserve room for status, post_op_attr, and path length */
- svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 1 + 22 + 1);
+ svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy,
+ 1 + NFS3_POST_OP_ATTR_WORDS + 1);
/* Read the symlink. */
+ fh_copy(&resp->fh, &argp->fh);
resp->len = NFS3_MAXPATHLEN;
- nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
- fh_put(&argp->fh);
+ nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len);
RETURN(nfserr);
}
/*
* Read a portion of a file.
- * N.B. After this call resp->fh needs an fh_put
*/
static int
nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
@@ -152,9 +173,9 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
u32 * buffer;
int nfserr, avail;
- dprintk("nfsd: READ %x/%ld %lu bytes at %lu\n",
+ dprintk("nfsd: READ(3) %x/%ld %lu bytes at %lu\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
(unsigned long) argp->count,
(unsigned long) argp->offset);
@@ -162,30 +183,29 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
* 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
* + 1 (xdr opaque byte count) = 26
*/
- svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &avail, 26);
-
- if ((avail << 2) < argp->count) {
- printk(KERN_NOTICE
- "oversized read request from %08lx:%d (%d bytes)\n",
- ntohl(rqstp->rq_addr.sin_addr.s_addr),
- ntohs(rqstp->rq_addr.sin_port),
- argp->count);
- argp->count = avail;
- }
+ svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &avail,
+ 1 + NFS3_POST_OP_ATTR_WORDS + 3);
resp->count = argp->count;
- resp->fh = argp->fh;
+ if ((avail << 2) < resp->count)
+ resp->count = avail << 2;
+
+ fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_read(rqstp, &resp->fh,
argp->offset,
(char *) buffer,
&resp->count);
+ if (nfserr == 0) {
+ struct inode *inode = resp->fh.fh_dentry->d_inode;
+
+ resp->eof = (argp->offset + resp->count) >= inode->i_size;
+ }
RETURN(nfserr);
}
/*
* Write data to a file
- * N.B. After this call resp->fh needs an fh_put
*/
static int
nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
@@ -193,19 +213,21 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
{
int nfserr;
- dprintk("nfsd: WRITE %x/%ld %d bytes at %ld\n",
+ dprintk("nfsd: WRITE(3) %x/%ld %d bytes at %ld%s\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
argp->len,
- (unsigned long) argp->offset);
+ (unsigned long) argp->offset,
+ argp->stable? " stable" : "");
- resp->fh = argp->fh;
+ fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_write(rqstp, &resp->fh,
argp->offset,
argp->data,
argp->len,
argp->stable);
resp->committed = argp->stable;
+ resp->count = argp->count;
RETURN(nfserr);
}
@@ -213,20 +235,18 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
* With NFSv3, CREATE processing is a lot easier than with NFSv2.
* At least in theory; we'll see how it fares in practice when the
* first reports about SunOS compatibility problems start to pour in...
- * N.B. After this call _both_ resp->dirfh and resp->fh need an fh_put
*/
static int
nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
- struct nfsd3_createres *resp)
+ struct nfsd3_diropres *resp)
{
svc_fh *dirfhp, *newfhp = NULL;
struct iattr *attr;
- int mode;
u32 nfserr;
- dprintk("nfsd: CREATE %x/%ld %s\n",
+ dprintk("nfsd: CREATE(3) %x/%ld %s\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
argp->name);
dirfhp = fh_copy(&resp->dirfh, &argp->fh);
@@ -243,303 +263,427 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
if (!(attr->ia_valid & ATTR_MODE)) {
attr->ia_valid |= ATTR_MODE;
attr->ia_mode = S_IFREG;
+ } else {
+ attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG;
}
- mode = attr->ia_mode & ~S_IFMT;
/* Now create the file and set attributes */
- nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len,
- attr, S_IFREG, 0, newfhp);
+ nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len,
+ attr, newfhp,
+ argp->createmode, argp->verf);
+
+ RETURN(nfserr);
+}
+
+/*
+ * Make directory. This operation is not idempotent.
+ */
+static int
+nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
+ struct nfsd3_diropres *resp)
+{
+ int nfserr;
+
+ dprintk("nfsd: MKDIR(3) %x/%ld %s\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
+ argp->name);
+
+ argp->attrs.ia_valid &= ~ATTR_SIZE;
+ fh_copy(&resp->dirfh, &argp->fh);
+ fh_init(&resp->fh);
+ nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
+ &argp->attrs, S_IFDIR, 0, &resp->fh);
RETURN(nfserr);
}
-/* N.B. Is nfsd3_attrstat * correct for resp?? table says "void" */
+static int
+nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
+ struct nfsd3_diropres *resp)
+{
+ int nfserr;
+
+ dprintk("nfsd: SYMLINK(3) %x/%ld %s -> %s\n",
+ SVCFH_DEV(&argp->ffh),
+ (long)SVCFH_INO(&argp->ffh),
+ argp->fname, argp->tname);
+
+ fh_copy(&resp->dirfh, &argp->ffh);
+ fh_init(&resp->fh);
+ nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
+ argp->tname, argp->tlen,
+ &resp->fh, &argp->attrs);
+ RETURN(nfserr);
+}
+
+/*
+ * Make socket/fifo/device.
+ */
+static int
+nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp,
+ struct nfsd3_diropres *resp)
+{
+ int nfserr, type;
+ dev_t rdev = 0;
+
+ dprintk("nfsd: MKNOD(3) %x/%ld %s\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
+ argp->name);
+
+ fh_copy(&resp->dirfh, &argp->fh);
+ fh_init(&resp->fh);
+
+ if (argp->ftype == 0 || argp->ftype >= NF3BAD)
+ return nfserr_inval;
+ if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
+ if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV)
+ || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
+ || argp->minor > 0xFF)
+ return nfserr_inval;
+ rdev = ((argp->major) << 8) | (argp->minor);
+ } else
+ if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
+ return nfserr_inval;
+
+ type = nfs3_ftypes[argp->ftype];
+ nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
+ &argp->attrs, type, rdev, &resp->fh);
+
+ RETURN(nfserr);
+}
+
+/*
+ * Remove file/fifo/socket etc.
+ */
static int
nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
struct nfsd3_attrstat *resp)
{
int nfserr;
- dprintk("nfsd: REMOVE %x/%ld %s\n",
+ dprintk("nfsd: REMOVE(3) %x/%ld %s\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
argp->name);
- /* Is this correct?? */
- fh_copy(&resp->fh, &argp->fh);
-
/* Unlink. -S_IFDIR means file must not be a directory */
+ fh_copy(&resp->fh, &argp->fh);
nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
- /*
- * N.B. Should be an fh_put here ... nfsd3_proc_rmdir has one,
- * or else as an xdr release function
- */
- fh_put(&resp->fh);
+ RETURN(nfserr);
+}
+
+/*
+ * Remove a directory
+ */
+static int
+nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
+ struct nfsd3_attrstat *resp)
+{
+ int nfserr;
+
+ dprintk("nfsd: RMDIR(3) %x/%ld %s\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
+ argp->name);
+
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
RETURN(nfserr);
}
static int
nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp,
- void *resp)
+ struct nfsd3_renameres *resp)
{
int nfserr;
- dprintk("nfsd: RENAME %x/%ld %s -> %x/%ld %s\n",
+ dprintk("nfsd: RENAME(3) %x/%ld %s -> %x/%ld %s\n",
SVCFH_DEV(&argp->ffh),
- SVCFH_INO(&argp->ffh),
+ (long)SVCFH_INO(&argp->ffh),
argp->fname,
SVCFH_DEV(&argp->tfh),
- SVCFH_INO(&argp->tfh),
+ (long)SVCFH_INO(&argp->tfh),
argp->tname);
- nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
- &argp->tfh, argp->tname, argp->tlen);
- fh_put(&argp->ffh);
- fh_put(&argp->tfh);
+ fh_copy(&resp->ffh, &argp->ffh);
+ fh_copy(&resp->tfh, &argp->tfh);
+ nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
+ &resp->tfh, argp->tname, argp->tlen);
RETURN(nfserr);
}
static int
nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp,
- void *resp)
+ struct nfsd3_linkres *resp)
{
int nfserr;
- dprintk("nfsd: LINK %x/%ld -> %x/%ld %s\n",
+ dprintk("nfsd: LINK(3) %x/%ld -> %x/%ld %s\n",
SVCFH_DEV(&argp->ffh),
- SVCFH_INO(&argp->ffh),
+ (long)SVCFH_INO(&argp->ffh),
SVCFH_DEV(&argp->tfh),
- SVCFH_INO(&argp->tfh),
+ (long)SVCFH_INO(&argp->tfh),
argp->tname);
- nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
- &argp->ffh);
- fh_put(&argp->ffh);
- fh_put(&argp->tfh);
+ fh_copy(&resp->fh, &argp->ffh);
+ fh_copy(&resp->tfh, &argp->tfh);
+ nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
+ &resp->fh);
RETURN(nfserr);
}
+/*
+ * Read a portion of a directory.
+ */
static int
-nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp,
- void *resp)
+nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
+ struct nfsd3_readdirres *resp)
{
- struct svc_fh newfh;
- int nfserr;
+ u32 * buffer;
+ int nfserr, count;
+ unsigned int want;
- dprintk("nfsd: SYMLINK %x/%ld %s -> %s\n",
- SVCFH_DEV(&argp->ffh),
- SVCFH_INO(&argp->ffh),
- argp->fname, argp->tname);
+ dprintk("nfsd: READDIR(3) %x/%ld %d bytes at %d\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh),
+ argp->count, (u32) argp->cookie);
- memset(&newfh, 0, sizeof(newfh));
+ /* Reserve buffer space for status, attributes and verifier */
+ svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count,
+ 1 + NFS3_POST_OP_ATTR_WORDS + 2);
- /*
- * Create the link, look up new file and set attrs.
- */
- nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
- argp->tname, argp->tlen,
- &newfh);
- if (!nfserr) {
- argp->attrs.ia_valid &= ~ATTR_SIZE;
- nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs);
- }
+ /* Make sure we've room for the NULL ptr & eof flag, and shrink to
+ * client read size */
+ if ((count -= 2) > (want = (argp->count >> 2) - 2))
+ count = want;
+
+ /* Read directory and encode entries on the fly */
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
+ nfs3svc_encode_entry,
+ buffer, &count, argp->verf);
+ memcpy(resp->verf, argp->verf, 8);
+ resp->count = count;
- fh_put(&argp->ffh);
- fh_put(&newfh);
RETURN(nfserr);
}
/*
- * Make directory. This operation is not idempotent.
- * N.B. After this call resp->fh needs an fh_put
+ * Read a portion of a directory, including file handles and attrs.
+ * For now, we choose to ignore the dircount parameter.
*/
static int
-nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
- struct nfsd3_diropres *resp)
+nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
+ struct nfsd3_readdirres *resp)
{
- int nfserr;
+ u32 * buffer;
+ int nfserr, count, want;
- dprintk("nfsd: MKDIR %x/%ld %s\n",
+ dprintk("nfsd: READDIR+(3) %x/%ld %d bytes at %d\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
- argp->name);
+ (long)SVCFH_INO(&argp->fh),
+ argp->count, (u32) argp->cookie);
+
+ /* Reserve buffer space for status, attributes and verifier */
+ svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count,
+ 1 + NFS3_POST_OP_ATTR_WORDS + 2);
+
+ /* Make sure we've room for the NULL ptr & eof flag, and shrink to
+ * client read size */
+ if ((count -= 2) > (want = argp->count >> 2))
+ count = want;
+
+ /* Read directory and encode entries on the fly */
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t) argp->cookie,
+ nfs3svc_encode_entry_plus,
+ buffer, &count, argp->verf);
+ memcpy(resp->verf, argp->verf, 8);
+ resp->count = count;
- argp->attrs.ia_valid &= ~ATTR_SIZE;
- nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
- &argp->attrs, S_IFDIR, 0, &resp->fh);
- fh_put(&argp->fh);
RETURN(nfserr);
}
/*
- * Remove a directory
+ * Get file system stats
*/
static int
-nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp,
- void *resp)
+nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
+ struct nfsd3_fsstatres *resp)
{
int nfserr;
- dprintk("nfsd: RMDIR %x/%ld %s\n",
+ dprintk("nfsd: FSSTAT(3) %x/%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
- argp->name);
+ (long)SVCFH_INO(&argp->fh));
- nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
+ nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
fh_put(&argp->fh);
RETURN(nfserr);
}
/*
- * Read a portion of a directory.
+ * Get file system info
*/
static int
-nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp,
- struct nfsd3_readdirres *resp)
+nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
+ struct nfsd3_fsinfores *resp)
{
- u32 * buffer;
- int nfserr, count;
+ int nfserr;
- dprintk("nfsd: READDIR %x/%ld %d bytes at %d\n",
+ dprintk("nfsd: FSINFO(3) %x/%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh),
- argp->count, argp->cookie);
+ (long)SVCFH_INO(&argp->fh));
+
+ resp->f_rtmax = NFSSVC_MAXBLKSIZE;
+ resp->f_rtpref = NFSSVC_MAXBLKSIZE;
+ resp->f_rtmult = PAGE_SIZE;
+ resp->f_wtmax = NFSSVC_MAXBLKSIZE;
+ resp->f_wtpref = NFSSVC_MAXBLKSIZE;
+ resp->f_wtmult = PAGE_SIZE;
+ resp->f_dtpref = PAGE_SIZE;
+ resp->f_maxfilesize = ~(u32) 0;
+ resp->f_properties = NFS3_FSF_DEFAULT;
+
+ nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
+
+ /* Check special features of the file system. May request
+ * different read/write sizes for file systems known to have
+ * problems with large blocks */
+ if (nfserr == 0) {
+ struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+
+ /* Note that we don't care for remote fs's here */
+ if (sb->s_magic == 0x4d44 /* MSDOS_SUPER_MAGIC */) {
+ resp->f_properties = NFS3_FSF_BILLYBOY;
+ }
+ }
- /* Reserve buffer space for status */
- svcbuf_reserve(&rqstp->rq_resbuf, &buffer, &count, 1);
+ fh_put(&argp->fh);
+ RETURN(nfserr);
+}
- /* Make sure we've room for the NULL ptr & eof flag, and shrink to
- * client read size */
- if ((count -= 8) > argp->count)
- count = argp->count;
+/*
+ * Get pathconf info for the specified file
+ */
+static int
+nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
+ struct nfsd3_pathconfres *resp)
+{
+ int nfserr;
- /* Read directory and encode entries on the fly */
- nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie,
- nfssvc_encode_entry,
- buffer, &count);
- resp->count = count;
+ dprintk("nfsd: PATHCONF(3) %x/%ld\n",
+ SVCFH_DEV(&argp->fh),
+ (long)SVCFH_INO(&argp->fh));
+
+ /* Set default pathconf */
+ resp->p_link_max = 255; /* at least */
+ resp->p_name_max = 255; /* at least */
+ resp->p_no_trunc = 0;
+ resp->p_chown_restricted = 1;
+ resp->p_case_insensitive = 0;
+ resp->p_case_preserving = 1;
+
+ nfserr = fh_verify(rqstp, &argp->fh, 0, MAY_NOP);
+
+ if (nfserr == 0) {
+ struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb;
+
+ /* Note that we don't care for remote fs's here */
+ switch (sb->s_magic) {
+ case EXT2_SUPER_MAGIC:
+ resp->p_link_max = EXT2_LINK_MAX;
+ resp->p_name_max = EXT2_NAME_LEN;
+ break;
+ case 0x4d44: /* MSDOS_SUPER_MAGIC */
+ resp->p_case_insensitive = 1;
+ resp->p_case_preserving = 0;
+ break;
+ }
+ }
fh_put(&argp->fh);
RETURN(nfserr);
}
+
/*
- * Get file system info
+ * Commit a file (range) to stable storage.
*/
static int
-nfsd3_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp,
- struct nfsd3_statfsres *resp)
+nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp,
+ struct nfsd3_commitres *resp)
{
int nfserr;
- dprintk("nfsd: STATFS %x/%ld\n",
+ dprintk("nfsd: COMMIT(3) %x/%ld %d@%ld\n",
SVCFH_DEV(&argp->fh),
- SVCFH_INO(&argp->fh));
+ (long)SVCFH_INO(&argp->fh),
+ argp->count,
+ (unsigned long) argp->offset);
+
+ if (argp->offset > NFS_OFFSET_MAX)
+ return nfserr_inval;
+
+ fh_copy(&resp->fh, &argp->fh);
+ nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
- nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
- fh_put(&argp->fh);
RETURN(nfserr);
}
+
/*
- * NFSv2 Server procedures.
+ * NFSv3 Server procedures.
* Only the results of non-idempotent operations are cached.
*/
-#define nfsd3_proc_none NULL
-#define nfssvc_encode_void NULL
-#define nfssvc_decode_void NULL
-#define nfssvc_release_void NULL
-struct nfsd3_void { int dummy; };
+#define nfs3svc_decode_voidargs NULL
+#define nfs3svc_release_void NULL
+#define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle
+#define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat
+#define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat
+#define nfsd3_mkdirargs nfsd3_createargs
+#define nfsd3_readdirplusargs nfsd3_readdirargs
+#define nfsd3_fhandleargs nfsd_fhandle
+#define nfsd3_fhandleres nfsd3_attrstat
+#define nfsd3_attrstatres nfsd3_attrstat
+#define nfsd3_wccstatres nfsd3_attrstat
+#define nfsd3_createres nfsd3_diropres
+#define nfsd3_voidres nfsd3_voidargs
+struct nfsd3_voidargs { int dummy; };
#define PROC(name, argt, rest, relt, cache) \
- { (svc_procfunc) nfsd3_proc_##name, \
- (kxdrproc_t) nfssvc_decode_##argt, \
- (kxdrproc_t) nfssvc_encode_##rest, \
- (kxdrproc_t) nfssvc_release_##relt, \
- sizeof(struct nfsd3_##argt), \
- sizeof(struct nfsd3_##rest), \
- 0, \
- cache \
+ { (svc_procfunc) nfsd3_proc_##name, \
+ (kxdrproc_t) nfs3svc_decode_##argt##args, \
+ (kxdrproc_t) nfs3svc_encode_##rest##res, \
+ (kxdrproc_t) nfs3svc_release_##relt, \
+ sizeof(struct nfsd3_##argt##args), \
+ sizeof(struct nfsd3_##rest##res), \
+ 0, \
+ cache \
}
-struct svc_procedure nfsd3_procedures2[18] = {
+struct svc_procedure nfsd_procedures3[22] = {
PROC(null, void, void, void, RC_NOCACHE),
PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE),
- PROC(setattr, sattrargs, attrstat, fhandle, RC_REPLBUFF),
- PROC(none, void, void, void, RC_NOCACHE),
- PROC(lookup, diropargs, diropres, fhandle2,RC_NOCACHE),
- PROC(readlink, fhandle, readlinkres, void, RC_NOCACHE),
- PROC(read, readargs, readres, fhandle, RC_NOCACHE),
- PROC(none, void, void, void, RC_NOCACHE),
- PROC(write, writeargs, attrstat, fhandle, RC_REPLBUFF),
- PROC(create, createargs, diropres, fhandle2,RC_REPLBUFF),
- PROC(remove, diropargs, void,/* ??*/ void, RC_REPLSTAT),
- PROC(rename, renameargs, void, void, RC_REPLSTAT),
- PROC(link, linkargs, void, void, RC_REPLSTAT),
- PROC(symlink, symlinkargs, void, void, RC_REPLSTAT),
- PROC(mkdir, createargs, diropres, fhandle, RC_REPLBUFF),
- PROC(rmdir, diropargs, void, void, RC_REPLSTAT),
- PROC(readdir, readdirargs, readdirres, void, RC_REPLSTAT),
- PROC(statfs, fhandle, statfsres, void, RC_NOCACHE),
+ PROC(setattr, sattr, wccstat, fhandle, RC_REPLBUFF),
+ PROC(lookup, dirop, dirop, fhandle2, RC_NOCACHE),
+ PROC(access, access, access, fhandle, RC_NOCACHE),
+ PROC(readlink, fhandle, readlink, fhandle, RC_NOCACHE),
+ PROC(read, read, read, fhandle, RC_NOCACHE),
+ PROC(write, write, write, fhandle, RC_REPLBUFF),
+ PROC(create, create, create, fhandle2, RC_REPLBUFF),
+ PROC(mkdir, mkdir, create, fhandle2, RC_REPLBUFF),
+ PROC(symlink, symlink, create, fhandle2, RC_REPLBUFF),
+ PROC(mknod, mknod, create, fhandle2, RC_REPLBUFF),
+ PROC(remove, dirop, wccstat, fhandle, RC_REPLBUFF),
+ PROC(rmdir, dirop, wccstat, fhandle, RC_REPLBUFF),
+ PROC(rename, rename, rename, fhandle, RC_REPLBUFF),
+ PROC(link, link, link, fhandle2, RC_REPLBUFF),
+ PROC(readdir, readdir, readdir, fhandle, RC_NOCACHE),
+ PROC(readdirplus,readdirplus, readdir, fhandle, RC_NOCACHE),
+ PROC(fsstat, fhandle, fsstat, void, RC_NOCACHE),
+ PROC(fsinfo, fhandle, fsinfo, void, RC_NOCACHE),
+ PROC(pathconf, fhandle, pathconf, void, RC_NOCACHE),
+ PROC(commit, commit, commit, fhandle, RC_NOCACHE)
};
-
-
-/*
- * Map errnos to NFS errnos.
- */
-int
-nfserrno (int errno)
-{
- static struct {
- int nfserr;
- int syserr;
- } nfs_errtbl[] = {
- { NFS_OK, 0 },
- { NFSERR_PERM, EPERM },
- { NFSERR_NOENT, ENOENT },
- { NFSERR_IO, EIO },
- { NFSERR_NXIO, ENXIO },
- { NFSERR_ACCES, EACCES },
- { NFSERR_EXIST, EEXIST },
- { NFSERR_NODEV, ENODEV },
- { NFSERR_NOTDIR, ENOTDIR },
- { NFSERR_ISDIR, EISDIR },
- { NFSERR_INVAL, EINVAL },
- { NFSERR_FBIG, EFBIG },
- { NFSERR_NOSPC, ENOSPC },
- { NFSERR_ROFS, EROFS },
- { NFSERR_NAMETOOLONG, ENAMETOOLONG },
- { NFSERR_NOTEMPTY, ENOTEMPTY },
-#ifdef EDQUOT
- { NFSERR_DQUOT, EDQUOT },
-#endif
- { NFSERR_STALE, ESTALE },
- { NFSERR_WFLUSH, EIO },
- { -1, EIO }
- };
- int i;
-
- for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
- if (nfs_errtbl[i].syserr == errno)
- return htonl (nfs_errtbl[i].nfserr);
- }
- printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
- return nfserr_io;
-}
-
-#if 0
-static void
-nfsd3_dump(char *tag, u32 *buf, int len)
-{
- int i;
-
- printk(KERN_NOTICE
- "nfsd: %s (%d words)\n", tag, len);
-
- for (i = 0; i < len && i < 32; i += 8)
- printk(KERN_NOTICE
- " %08lx %08lx %08lx %08lx"
- " %08lx %08lx %08lx %08lx\n",
- buf[i], buf[i+1], buf[i+2], buf[i+3],
- buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
-}
-#endif
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 31a5ef887..95e8e8424 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -3,7 +3,7 @@
*
* XDR support for nfsd/protocol version 3.
*
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/types.h>
@@ -17,16 +17,16 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR
-u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
- nfserr_acces, nfserr_exist, nfserr_nodev, nfserr_notdir,
- nfserr_isdir, nfserr_fbig, nfserr_nospc, nfserr_rofs,
- nfserr_nametoolong, nfserr_dquot, nfserr_stale;
-
#ifdef NFSD_OPTIMIZE_SPACE
# define inline
#endif
/*
+ * Size of encoded NFS3 file handle, in words
+ */
+#define NFS3_FHANDLE_WORDS (1 + XDR_QUADLEN(sizeof(struct knfs_fh)))
+
+/*
* Mapping of S_IF* types to NFS file types
*/
static u32 nfs3_ftypes[] = {
@@ -37,48 +37,9 @@ static u32 nfs3_ftypes[] = {
};
/*
- * Initialization of NFS status variables
- */
-void
-nfs3xdr_init(void)
-{
- static int inited = 0;
-
- if (inited)
- return;
-
- nfs_ok = htonl(NFS_OK);
- nfserr_perm = htonl(NFSERR_PERM);
- nfserr_noent = htonl(NFSERR_NOENT);
- nfserr_io = htonl(NFSERR_IO);
- nfserr_nxio = htonl(NFSERR_NXIO);
- nfserr_acces = htonl(NFSERR_ACCES);
- nfserr_exist = htonl(NFSERR_EXIST);
- nfserr_nodev = htonl(NFSERR_NODEV);
- nfserr_notdir = htonl(NFSERR_NOTDIR);
- nfserr_isdir = htonl(NFSERR_ISDIR);
- nfserr_fbig = htonl(NFSERR_FBIG);
- nfserr_nospc = htonl(NFSERR_NOSPC);
- nfserr_rofs = htonl(NFSERR_ROFS);
- nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
- nfserr_dquot = htonl(NFSERR_DQUOT);
- nfserr_stale = htonl(NFSERR_STALE);
-
- inited = 1;
-}
-
-/*
* XDR functions for basic NFS types
*/
static inline u32 *
-enc64(u32 *p, u64 val)
-{
- *p++ = (val >> 32);
- *p++ = (val & 0xffffffff);
- return p;
-}
-
-static inline u32 *
dec64(u32 *p, u64 *valp)
{
*valp = ((u64) ntohl(*p++)) << 32;
@@ -103,13 +64,10 @@ decode_time3(u32 *p, time_t *secp)
static inline u32 *
decode_fh(u32 *p, struct svc_fh *fhp)
{
- if (*p++ != sizeof(struct knfs_fh))
+ if (ntohl(*p++) != sizeof(struct knfs_fh))
return NULL;
memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
- fhp->fh_inode = NULL;
- fhp->fh_export = NULL;
-
return p + (sizeof(struct knfs_fh) >> 2);
}
@@ -179,27 +137,35 @@ decode_sattr3(u32 *p, struct iattr *iap)
iap->ia_gid = ntohl(*p++);
}
if (*p++) {
+ u64 newsize;
+
iap->ia_valid |= ATTR_SIZE;
- iap->ia_size = ntohl(*p++);
+ p = dec64(p, &newsize);
+ if (newsize <= NFS_OFFSET_MAX)
+ iap->ia_size = (u32) newsize;
+ else
+ iap->ia_size = ~(size_t) 0;
}
- if ((tmp = *p++) == 1) {
+ if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
iap->ia_valid |= ATTR_ATIME;
- } else if (tmp == 2) {
+ } else if (tmp == 2) { /* set to client time */
iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
iap->ia_atime = ntohl(*p++), p++;
}
- if ((tmp = *p++) != 0) {
- iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
- } else if (tmp == 2) {
+ if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
iap->ia_valid |= ATTR_MTIME;
+ } else if (tmp == 2) { /* set to client time */
+ iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
iap->ia_mtime = ntohl(*p++), p++;
}
return p;
}
static inline u32 *
-encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
+encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
{
+ struct inode *inode = dentry->d_inode;
+
if (!inode) {
printk("nfsd: NULL inode in %s:%d", __FILE__, __LINE__);
return NULL;
@@ -227,19 +193,50 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
return p;
}
+static inline u32 *
+encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ struct inode *inode = fhp->fh_dentry->d_inode;
+
+ /* Attributes to follow */
+ *p++ = xdr_one;
+
+ *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
+ *p++ = htonl((u32) fhp->fh_post_mode);
+ *p++ = htonl((u32) fhp->fh_post_nlink);
+ *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
+ *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
+ if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
+ p = enc64(p, (u64) NFS3_MAXPATHLEN);
+ } else {
+ p = enc64(p, (u64) fhp->fh_post_size);
+ }
+ p = enc64(p, fhp->fh_post_blksize * fhp->fh_post_blocks);
+ *p++ = htonl((u32) MAJOR(fhp->fh_post_rdev));
+ *p++ = htonl((u32) MINOR(fhp->fh_post_rdev));
+ p = enc64(p, (u64) inode->i_dev);
+ p = enc64(p, (u64) inode->i_ino);
+ p = encode_time3(p, fhp->fh_post_atime);
+ p = encode_time3(p, fhp->fh_post_mtime);
+ p = encode_time3(p, fhp->fh_post_ctime);
+
+ return p;
+}
+
/*
* Encode post-operation attributes.
* The inode may be NULL if the call failed because of a stale file
* handle. In this case, no attributes are returned.
*/
static u32 *
-encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
+encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
{
- if (inode == NULL) {
- *p++ = xdr_zero;
- return p;
+ if (dentry && dentry->d_inode != NULL) {
+ *p++ = xdr_one; /* attributes follow */
+ return encode_fattr3(rqstp, p, dentry);
}
- return encode_fattr3(rqstp, p, inode);
+ *p++ = xdr_zero;
+ return p;
}
/*
@@ -248,17 +245,22 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
static u32 *
encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
{
- struct inode *inode = fhp->fh_inode;
+ struct dentry *dentry = fhp->fh_dentry;
- if (fhp->fh_post_version == inode->i_version) {
- *p++ = xdr_one;
- p = enc64(p, (u64) fhp->fh_pre_size);
- p = encode_time3(p, fhp->fh_pre_mtime);
- p = encode_time3(p, fhp->fh_pre_ctime);
- } else {
- *p++ = xdr_zero;
+ if (dentry && dentry->d_inode && fhp->fh_post_saved) {
+ if (fhp->fh_pre_saved) {
+ *p++ = xdr_one;
+ p = enc64(p, (u64) fhp->fh_pre_size);
+ p = encode_time3(p, fhp->fh_pre_mtime);
+ p = encode_time3(p, fhp->fh_pre_ctime);
+ } else {
+ *p++ = xdr_zero;
+ }
+ return encode_saved_post_attr(rqstp, p, fhp);
}
- return encode_post_op_attr(rqstp, p, inode);
+ /* no pre- or post-attrs */
+ *p++ = xdr_zero;
+ return encode_post_op_attr(rqstp, p, dentry);
}
/*
@@ -299,10 +301,12 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_sattrargs *args)
{
if (!(p = decode_fh(p, &args->fh))
- || !(p = decode_sattr3(p, &args->attrs))
- || (*p++ && !(p = decode_time3(p, &args->guardtime))))
+ || !(p = decode_sattr3(p, &args->attrs)))
return 0;
+ if ((args->check_guard = ntohl(*p++)) != 0)
+ p = decode_time3(p, &args->guardtime);
+
return xdr_argsize_check(rqstp, p);
}
@@ -333,10 +337,10 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readargs *args)
{
if (!(p = decode_fh(p, &args->fh))
- || !(p = dec64(p, &args->offset))
- || !(p = dec64(p, &args->count)))
+ || !(p = dec64(p, &args->offset)))
return 0;
+ args->count = ntohl(*p++);
return xdr_argsize_check(rqstp, p);
}
@@ -345,14 +349,14 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_writeargs *args)
{
if (!(p = decode_fh(p, &args->fh))
- || !(p = dec64(p, &args->offset))
- || !(p = dec64(p, &args->count)))
+ || !(p = dec64(p, &args->offset)))
return 0;
+ args->count = ntohl(*p++);
args->stable = ntohl(*p++);
args->len = ntohl(*p++);
args->data = (char *) p;
- p += (args->len + 3) >> 2;
+ p += XDR_QUADLEN(args->len);
return xdr_argsize_check(rqstp, p);
}
@@ -366,11 +370,12 @@ nfs3svc_decode_createargs(struct svc_rqst *rqstp, u32 *p,
return 0;
switch (args->createmode = ntohl(*p++)) {
- case 0: case 1:
+ case NFS3_CREATE_UNCHECKED:
+ case NFS3_CREATE_GUARDED:
if (!(p = decode_sattr3(p, &args->attrs)))
return 0;
break;
- case 2:
+ case NFS3_CREATE_EXCLUSIVE:
args->verf = p;
p += 2;
break;
@@ -460,8 +465,9 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, u32 *p,
{
if (!(p = decode_fh(p, &args->fh)))
return 0;
- args->cookie = ntohl(*p++);
+ p = dec64(p, &args->cookie);
args->verf = p; p += 2;
+ args->dircount = ~0;
args->count = ntohl(*p++);
return xdr_argsize_check(rqstp, p);
@@ -473,7 +479,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, u32 *p,
{
if (!(p = decode_fh(p, &args->fh)))
return 0;
- args->cookie = ntohl(*p++);
+ p = dec64(p, &args->cookie);
args->verf = p; p += 2;
args->dircount = ntohl(*p++);
args->count = ntohl(*p++);
@@ -485,9 +491,9 @@ int
nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_commitargs *args)
{
- if (!(p = decode_fh(p, &args->fh))
- || !(p = dec64(p, &args->offset)))
+ if (!(p = decode_fh(p, &args->fh)))
return 0;
+ p = dec64(p, &args->offset);
args->count = ntohl(*p++);
return xdr_argsize_check(rqstp, p);
@@ -496,12 +502,23 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
/*
* XDR encode functions
*/
+/*
+ * There must be an encoding function for void results so svc_process
+ * will work properly.
+ */
+int
+nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
+{
+ return xdr_ressize_check(rqstp, p);
+}
+
/* GETATTR */
int
nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_attrstat *resp)
{
- if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
+ if (resp->status == 0
+ && !(p = encode_fattr3(rqstp, p, resp->fh.fh_dentry)))
return 0;
return xdr_ressize_check(rqstp, p);
}
@@ -518,15 +535,14 @@ nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
/* LOOKUP */
int
-nfs3svc_encode_lookupres(struct svc_rqst *rqstp, u32 *p,
- struct nfsd3_lookupres *resp)
+nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_diropres *resp)
{
if (resp->status == 0) {
p = encode_fh(p, &resp->fh);
- if (!(p = encode_fattr3(rqstp, p, resp->fh.fh_inode)))
- return 0;
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
}
- p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->dirfh.fh_dentry);
return xdr_ressize_check(rqstp, p);
}
@@ -535,7 +551,7 @@ int
nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_accessres *resp)
{
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
if (resp->status == 0)
*p++ = htonl(resp->access);
return xdr_ressize_check(rqstp, p);
@@ -546,7 +562,7 @@ int
nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readlinkres *resp)
{
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
if (resp->status == 0) {
*p++ = htonl(resp->len);
p += XDR_QUADLEN(resp->len);
@@ -559,7 +575,7 @@ int
nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readres *resp)
{
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
if (resp->status == 0) {
*p++ = htonl(resp->count);
*p++ = htonl(resp->eof);
@@ -587,11 +603,12 @@ nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
/* CREATE, MKDIR, SYMLINK, MKNOD */
int
nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
- struct nfsd3_createres *resp)
+ struct nfsd3_diropres *resp)
{
if (resp->status == 0) {
+ *p++ = xdr_one;
p = encode_fh(p, &resp->fh);
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
}
p = encode_wcc_data(rqstp, p, &resp->dirfh);
return xdr_ressize_check(rqstp, p);
@@ -612,7 +629,7 @@ int
nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_linkres *resp)
{
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
p = encode_wcc_data(rqstp, p, &resp->tfh);
return xdr_ressize_check(rqstp, p);
}
@@ -622,73 +639,116 @@ int
nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
struct nfsd3_readdirres *resp)
{
- p = encode_post_op_attr(rqstp, p, resp->fh.fh_inode);
+ p = encode_post_op_attr(rqstp, p, resp->fh.fh_dentry);
if (resp->status == 0) {
/* stupid readdir cookie */
- *p++ = ntohl(resp->fh.fh_inode->i_mtime);
- *p++ = xdr_zero;
- p = resp->list_end;
+ memcpy(p, resp->verf, 8); p += 2;
+ p += XDR_QUADLEN(resp->count);
}
return xdr_ressize_check(rqstp, p);
}
-#define NFS3_ENTRYPLUS_BAGGAGE ((1 + 20 + 1 + NFS3_FHSIZE) << 2)
-int
-nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
- int namlen, unsigned long offset, ino_t ino)
+/*
+ * Encode a directory entry. This one works for both normal readdir
+ * and readdirplus.
+ * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
+ * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
+ *
+ * The readdirplus baggage is 1+21 words for post_op_attr, plus the
+ * file handle.
+ */
+
+#define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1)
+#define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
+static int
+encode_entry(struct readdir_cd *cd, const char *name,
+ int namlen, off_t offset, ino_t ino, int plus)
{
u32 *p = cd->buffer;
int buflen, slen, elen;
- struct svc_fh fh;
- if (offset > ~((u64) 0))
- return -EINVAL;
if (cd->offset)
- *cd->offset = htonl(offset);
+ enc64(cd->offset, (u64) offset);
- /* For readdirplus, look up the inode */
- if (cd->plus && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh))
+ /* nfsd_readdir calls us with name == 0 when it wants us to
+ * set the last offset entry. */
+ if (name == 0)
return 0;
+ /*
+ dprintk("encode_entry(%.*s @%ld%s)\n",
+ namlen, name, (long) offset, plus? " plus" : "");
+ */
+
/* truncate filename if too long */
if (namlen > NFS3_MAXNAMLEN)
namlen = NFS3_MAXNAMLEN;
slen = XDR_QUADLEN(namlen);
- elen = slen + (cd->plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
- if ((buflen = cd->buflen - elen - 4) < 0) {
+ elen = slen + NFS3_ENTRY_BAGGAGE
+ + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
+ if ((buflen = cd->buflen - elen) < 0) {
cd->eob = 1;
- if (cd->plus)
- fh_put(&fh);
return -EINVAL;
}
- *p++ = xdr_one; /* mark entry present */
- *p++ = xdr_zero; /* file id (64 bit) */
- *p++ = htonl((u32) ino);
- *p++ = htonl((u32) namlen); /* name length & name */
+ *p++ = xdr_one; /* mark entry present */
+ p = enc64(p, ino); /* file id */
+#ifdef XDR_ENCODE_STRING_TAKES_LENGTH
+ p = xdr_encode_string(p, name, namlen); /* name length & name */
+#else
+ /* just like nfsproc.c */
+ *p++ = htonl((u32) namlen);
memcpy(p, name, namlen);
p += slen;
+#endif
+ p[slen - 1] = 0; /* don't leak kernel data */
+
+ cd->offset = p; /* remember pointer */
+ p = enc64(p, NFS_OFFSET_MAX); /* offset of next entry */
/* throw in readdirplus baggage */
- if (cd->plus) {
- p = encode_post_op_attr(cd->rqstp, p, fh.fh_inode);
- p = encode_fh(p, &fh);
- fh_put(&fh);
+ if (plus) {
+ struct svc_fh fh;
+
+ fh_init(&fh);
+ /* Disabled for now because of lock-up */
+ if (0 && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh) == 0) {
+ p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
+ p = encode_fh(p, &fh);
+ fh_put(&fh);
+ } else {
+ /* Didn't find this entry... weird.
+ * Proceed without the attrs anf fh anyway.
+ */
+ *p++ = 0;
+ *p++ = 0;
+ }
}
- cd->offset = p; /* remember pointer */
- p = enc64(p, ~(u64) 0); /* offset of next entry */
-
cd->buflen = buflen;
cd->buffer = p;
return 0;
}
+int
+nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
+ int namlen, off_t offset, ino_t ino)
+{
+ return encode_entry(cd, name, namlen, offset, ino, 0);
+}
+
+int
+nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
+ int namlen, off_t offset, ino_t ino)
+{
+ return encode_entry(cd, name, namlen, offset, ino, 1);
+}
+
/* FSSTAT */
int
-nfs3svc_encode_statfsres(struct svc_rqst *rqstp, u32 *p,
- struct nfsd3_statfsres *resp)
+nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_fsstatres *resp)
{
struct statfs *s = &resp->stats;
u64 bs = s->f_bsize;
@@ -722,9 +782,9 @@ nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
*p++ = htonl(resp->f_wtpref);
*p++ = htonl(resp->f_wtmult);
*p++ = htonl(resp->f_dtpref);
- *p++ = htonl(resp->f_maxfilesize);
+ p = enc64(p, resp->f_maxfilesize);
+ *p++ = xdr_one;
*p++ = xdr_zero;
- *p++ = htonl(1000000000 / HZ);
*p++ = htonl(resp->f_properties);
}
@@ -741,8 +801,8 @@ nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
if (resp->status == 0) {
*p++ = htonl(resp->p_link_max);
*p++ = htonl(resp->p_name_max);
- *p++ = xdr_one; /* always reject long file names */
- *p++ = xdr_one; /* chown restricted */
+ *p++ = htonl(resp->p_no_trunc);
+ *p++ = htonl(resp->p_chown_restricted);
*p++ = htonl(resp->p_case_insensitive);
*p++ = htonl(resp->p_case_preserving);
}
@@ -769,7 +829,7 @@ nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
*/
int
nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
- struct nfsd_fhandle *resp)
+ struct nfsd3_attrstat *resp)
{
fh_put(&resp->fh);
return 1;
@@ -777,7 +837,7 @@ nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
int
nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
- struct nfsd3_fhandle2 *resp)
+ struct nfsd3_fhandle_pair *resp)
{
fh_put(&resp->fh1);
fh_put(&resp->fh2);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 8c575db4e..c41dff207 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -57,7 +57,7 @@ int exp_procfs_exports(char *buffer, char **start, off_t offset,
void proc_export_init(void)
{
- if (!create_proc_entry("fs/nfs", S_IFDIR, 0))
+ if (!proc_mkdir("fs/nfs", 0))
return;
create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 42ad50fe9..ce3b08e9d 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -5,7 +5,7 @@
*
* Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
* Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
- * Extensive cleanup by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
+ * Extensive rewrite by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
*/
#include <linux/sched.h>
@@ -63,7 +63,7 @@ dprintk("filldir_one: seq=%d, ino=%ld, name=%s\n", buf->sequence, ino, name);
}
/*
- * Read a directory and return the name of the specified entry.
+ * Read a directory and return the name of the specified entry. i_sem is already down().
*/
static int get_ino_name(struct dentry *dentry, struct qstr *name, unsigned long ino)
{
@@ -94,9 +94,7 @@ static int get_ino_name(struct dentry *dentry, struct qstr *name, unsigned long
buffer.sequence = 0;
while (1) {
int old_seq = buffer.sequence;
- down(&dir->i_sem);
error = file.f_op->readdir(&file, &buffer, filldir_one);
- up(&dir->i_sem);
if (error < 0)
break;
@@ -118,7 +116,7 @@ out:
/* this should be provided by each filesystem in an nfsd_operations interface as
* iget isn't really the right interface
*/
-static inline struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
+static struct dentry *nfsd_iget(struct super_block *sb, unsigned long ino, __u32 generation)
{
/* iget isn't really right if the inode is currently unallocated!!
@@ -209,6 +207,7 @@ struct dentry *nfsd_findparent(struct dentry *child)
* it is well connected. But nobody returns different dentrys do they?
*/
pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
+ d_drop(tdentry); /* we never want ".." hashed */
if (!pdentry) {
/* I don't want to return a ".." dentry.
* I would prefer to return an unconnected "IS_ROOT" dentry,
@@ -233,10 +232,62 @@ struct dentry *nfsd_findparent(struct dentry *child)
if (pdentry == NULL)
pdentry = ERR_PTR(-ENOMEM);
}
- dput(tdentry); /* it was never rehashed, it will be discarded */
+ dput(tdentry); /* it is not hashed, it will be discarded */
return pdentry;
}
+static struct dentry *splice(struct dentry *child, struct dentry *parent)
+{
+ int err = 0;
+ struct qstr qs;
+ char namebuf[256];
+ struct list_head *lp;
+ struct dentry *tmp;
+ /* child is an IS_ROOT (anonymous) dentry, but it is hypothesised that
+ * it should be a child of parent.
+ * We see if we can find a name and, if we can - splice it in.
+ * We hold the i_sem on the parent the whole time to try to follow locking protocols.
+ */
+ qs.name = namebuf;
+ down(&parent->d_inode->i_sem);
+
+ /* Now, things might have changed while we waited.
+ * Possibly a friendly filesystem found child and spliced it in in response
+ * to a lookup (though nobody does this yet). In this case, just succeed.
+ */
+ if (child->d_parent == parent) goto out;
+ /* Possibly a new dentry has been made for this child->d_inode in parent by
+ * a lookup. In this case return that dentry. caller must notice and act accordingly
+ */
+ for (lp = child->d_inode->i_dentry.next; lp != &child->d_inode->i_dentry ; lp=lp->next) {
+ tmp = list_entry(lp,struct dentry, d_alias);
+ if (tmp->d_parent == parent) {
+ child = dget(tmp);
+ goto out;
+ }
+ }
+ /* well, if we can find a name for child in parent, it should be safe to splice it in */
+ err = get_ino_name(parent, &qs, child->d_inode->i_ino);
+ if (err)
+ goto out;
+ tmp = d_lookup(parent, &qs);
+ if (tmp) {
+ /* Now that IS odd. I wonder what it means... */
+ err = -EEXIST;
+ printk("nfsd-fh: found a name that I didn't expect: %s/%s\n", parent->d_name.name, qs.name);
+ dput(tmp);
+ goto out;
+ }
+ err = d_splice(child, parent, &qs);
+ dprintk("nfsd_fh: found name %s for ino %ld\n", child->d_name.name, child->d_inode->i_ino);
+ out:
+ up(&parent->d_inode->i_sem);
+ if (err)
+ return ERR_PTR(err);
+ else
+ return child;
+}
+
/*
* This is the basic lookup mechanism for turning an NFS file handle
* into a dentry.
@@ -248,15 +299,22 @@ static struct dentry *
find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
{
struct dentry *dentry, *result = NULL;
- struct qstr qs;
- char namebuf[256];
+ struct dentry *tmp;
int found =0;
u32 err;
+ /* This semaphore is needed to make sure that only one unconnected (free)
+ * dcache path ever exists, as otherwise two partial paths might get
+ * joined together, which would be very confusing.
+ * If there is ever an unconnected non-root directory, then this lock
+ * must be held. This could sensibly be per-filesystem.
+ */
+ static DECLARE_MUTEX(free_path_sem);
- qs.name = namebuf;
+ nfsdstats.fh_lookup++;
/*
* Attempt to find the inode.
*/
+ retry:
result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
err = PTR_ERR(result);
if (IS_ERR(result))
@@ -269,10 +327,11 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
if (!IS_ROOT(result) || result->d_inode->i_sb->s_root ==result)
return result;
- /* result is now a "root" dentry, which may be adequate as it stands, or else
+ /* result is now an anonymous dentry, which may be adequate as it stands, or else
* will get spliced into the dcache tree */
if (!S_ISDIR(result->d_inode->i_mode) && ! needpath) {
+ nfsdstats.fh_anon++;
return result;
}
@@ -280,8 +339,10 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
* location in the tree.
*/
dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
+ down(&free_path_sem);
found = 0;
if (!S_ISDIR(result->d_inode->i_mode)) {
+ nfsdstats.fh_nocache_nondir++;
if (fh->fh_dirino == 0)
goto err_result; /* don't know how to find parent */
else {
@@ -297,22 +358,26 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
}
if (!IS_ROOT(dentry) || dentry->d_inode->i_sb->s_root ==dentry)
found = 1;
- err = get_ino_name(dentry, &qs, result->d_inode->i_ino);
- if (err)
- goto err_dentry;
-
- /* OK, we have the name in parent of inode, lets fill in the dentry */
- err = d_splice(result, dentry, &qs);
- if (err)
+ tmp = splice(result, dentry);
+ err = PTR_ERR(tmp);
+ if (IS_ERR(tmp))
goto err_dentry;
+ if (tmp != result) {
+ /* it is safe to just use tmp instead, but we must discard result first */
+ d_drop(result);
+ dput(result);
+ result = tmp;
+ /* If !found, then this is really wierd, but it shouldn't hurt */
+ }
}
- }
- else
+ } else {
+ nfsdstats.fh_nocache_dir++;
dentry = dget(result);
+ }
while(!found) {
/* LOOP INVARIANT */
- /* haven't found a place in the tree yet, but we do have a path
+ /* haven't found a place in the tree yet, but we do have a free path
* from dentry down to result, and dentry is a directory.
* Have a hold on dentry and result */
struct dentry *pdentry;
@@ -334,23 +399,41 @@ find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
if (!IS_ROOT(pdentry) || parent->i_sb->s_root == pdentry)
found = 1;
- err = get_ino_name(pdentry, &qs, dentry->d_inode->i_ino);
- if (err) {
+ tmp = splice(dentry, pdentry);
+ if (tmp != dentry) {
+ /* Something wrong. We need to drop thw whole dentry->result path
+ * whatever it was
+ */
+ struct dentry *d;
+ for (d=result ; d ; d=(d->d_parent == d)?NULL:d->d_parent)
+ d_drop(d);
+ }
+ if (IS_ERR(tmp)) {
+ err = PTR_ERR(tmp);
dput(pdentry);
goto err_dentry;
}
- err = d_splice(dentry, pdentry, &qs);
- dprintk("nfsd_fh: found name %s for ino %ld\n", dentry->d_name.name, dentry->d_inode->i_ino);
+ if (tmp != dentry) {
+ /* we lost a race, try again
+ */
+ dput(tmp);
+ dput(dentry);
+ dput(result); /* this will discard the whole free path, so we can up the semaphore */
+ up(&free_path_sem);
+ goto retry;
+ }
dput(dentry);
dentry = pdentry;
}
dput(dentry);
+ up(&free_path_sem);
return result;
err_dentry:
dput(dentry);
err_result:
dput(result);
+ up(&free_path_sem);
err_out:
if (err == -ESTALE)
nfsdstats.fh_stale++;
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 7c3e24817..05cc8ef58 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -1,7 +1,10 @@
/*
* nfsproc2.c Process version 2 NFS requests.
+ * linux/fs/nfsd/nfs2proc.c
+ *
+ * Process version 2 NFS requests.
*
- * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de>
*/
#include <linux/linkage.h>
@@ -144,7 +147,7 @@ nfsd_proc_read(struct svc_rqst *rqstp, struct nfsd_readargs *argp,
ntohl(rqstp->rq_addr.sin_addr.s_addr),
ntohs(rqstp->rq_addr.sin_port),
argp->count);
- argp->count = avail;
+ argp->count = avail << 2;
}
resp->count = argp->count;
@@ -237,6 +240,9 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
if (nfserr)
goto done;
inode = newfhp->fh_dentry->d_inode;
+ if (inode && newfhp->fh_handle.fh_ino == 0)
+ /* inode might have been instantiated while we slept */
+ fh_update(newfhp);
/* Unfudge the mode bits */
if (attr->ia_valid & ATTR_MODE) {
@@ -258,7 +264,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
goto out_unlock;
attr->ia_valid |= ATTR_MODE;
- attr->ia_mode = type | mode;
+ attr->ia_mode = mode;
/* Special treatment for non-regular files according to the
* gospel of sun micro
@@ -270,19 +276,21 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
rdev = (dev_t) size;
if (type != S_IFBLK && type != S_IFCHR) {
rdev = 0;
- } else if (type == S_IFCHR && size == ~(u32) 0) {
+ } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) {
/* If you think you've seen the worst, grok this. */
- attr->ia_mode = S_IFIFO | mode;
type = S_IFIFO;
} else if (size != rdev) {
/* dev got truncated because of 16bit Linux dev_t */
- nfserr = nfserr_io; /* or nfserr_inval? */
+ nfserr = nfserr_inval;
goto out_unlock;
} else {
/* Okay, char or block special */
is_borc = 1;
}
+ /* we've used the SIZE information, so discard it */
+ attr->ia_valid &= ~ATTR_SIZE;
+
/* Make sure the type and device matches */
nfserr = nfserr_exist;
if (inode && (type != (inode->i_mode & S_IFMT) ||
@@ -381,7 +389,8 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
*/
nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen,
argp->tname, argp->tlen,
- &newfh);
+ &newfh, &argp->attrs);
+
if (!nfserr) {
argp->attrs.ia_valid &= ~ATTR_SIZE;
nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs);
@@ -439,8 +448,8 @@ static int
nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
struct nfsd_readdirres *resp)
{
- u32 * buffer;
- int nfserr, count;
+ u32 * buffer;
+ int nfserr, count;
dprintk("nfsd: READDIR %d/%d %d bytes at %d\n",
SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
@@ -460,7 +469,8 @@ nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp,
/* Read directory and encode entries on the fly */
nfserr = nfsd_readdir(rqstp, &argp->fh, (loff_t) argp->cookie,
- nfssvc_encode_entry, buffer, &count);
+ nfssvc_encode_entry,
+ buffer, &count, NULL);
resp->count = count;
fh_put(&argp->fh);
@@ -540,6 +550,8 @@ nfserrno (int errno)
{ NFSERR_NXIO, ENXIO },
{ NFSERR_ACCES, EACCES },
{ NFSERR_EXIST, EEXIST },
+ { NFSERR_XDEV, EXDEV },
+ { NFSERR_MLINK, EMLINK },
{ NFSERR_NODEV, ENODEV },
{ NFSERR_NOTDIR, ENOTDIR },
{ NFSERR_ISDIR, EISDIR },
@@ -547,39 +559,22 @@ nfserrno (int errno)
{ NFSERR_FBIG, EFBIG },
{ NFSERR_NOSPC, ENOSPC },
{ NFSERR_ROFS, EROFS },
+ { NFSERR_MLINK, EMLINK },
{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
{ NFSERR_NOTEMPTY, ENOTEMPTY },
#ifdef EDQUOT
{ NFSERR_DQUOT, EDQUOT },
#endif
{ NFSERR_STALE, ESTALE },
- { NFSERR_WFLUSH, EIO },
{ -1, EIO }
};
int i;
for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
if (nfs_errtbl[i].syserr == errno)
- return htonl (nfs_errtbl[i].nfserr);
+ return htonl(nfs_errtbl[i].nfserr);
}
printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
return nfserr_io;
}
-#if 0
-static void
-nfsd_dump(char *tag, u32 *buf, int len)
-{
- int i;
-
- printk(KERN_NOTICE
- "nfsd: %s (%d words)\n", tag, len);
-
- for (i = 0; i < len && i < 32; i += 8)
- printk(KERN_NOTICE
- " %08lx %08lx %08lx %08lx"
- " %08lx %08lx %08lx %08lx\n",
- buf[i], buf[i+1], buf[i+2], buf[i+3],
- buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
-}
-#endif
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 0057e1fa3..940460a1b 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -196,7 +196,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
kxdrproc_t xdr;
u32 nfserr;
- dprintk("nfsd_dispatch: proc %d\n", rqstp->rq_proc);
+ dprintk("nfsd_dispatch: vers %d proc %d\n",
+ rqstp->rq_vers, rqstp->rq_proc);
proc = rqstp->rq_procinfo;
/* Check whether we have this call in the cache. */
@@ -225,8 +226,20 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
svc_putlong(&rqstp->rq_resbuf, nfserr);
/* Encode result.
- * FIXME: Most NFSv3 calls return wcc data even when the call failed
+ * For NFSv2, additional info is never returned in case of an error.
*/
+#ifdef CONFIG_NFSD_V3
+ if (!(nfserr && rqstp->rq_vers == 2)) {
+ xdr = proc->pc_encode;
+ if (xdr && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
+ /* Failed to encode result. Release cache entry */
+ dprintk("nfsd: failed to encode result!\n");
+ nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
+ *statp = rpc_system_err;
+ return 1;
+ }
+ }
+#else
xdr = proc->pc_encode;
if (!nfserr && xdr
&& !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
@@ -236,6 +249,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
*statp = rpc_system_err;
return 1;
}
+#endif /* CONFIG_NFSD_V3 */
/* Store reply in cache. */
nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
@@ -245,16 +259,16 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
static struct svc_version nfsd_version2 = {
2, 18, nfsd_procedures2, nfsd_dispatch
};
-#ifdef CONFIG_NFSD_NFS3
+#ifdef CONFIG_NFSD_V3
static struct svc_version nfsd_version3 = {
- 3, 23, nfsd_procedures3, nfsd_dispatch
+ 3, 22, nfsd_procedures3, nfsd_dispatch
};
#endif
static struct svc_version * nfsd_version[] = {
NULL,
NULL,
&nfsd_version2,
-#ifdef CONFIG_NFSD_NFS3
+#ifdef CONFIG_NFSD_V3
&nfsd_version3,
#endif
};
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 1d9a9dd5a..3afe9f83e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -18,9 +18,14 @@
#define NFSDDBG_FACILITY NFSDDBG_XDR
u32 nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
- nfserr_inval, nfserr_acces, nfserr_exist, nfserr_nodev, nfserr_notdir,
- nfserr_isdir, nfserr_fbig, nfserr_nospc, nfserr_rofs,
- nfserr_nametoolong, nfserr_dquot, nfserr_stale;
+ nfserr_acces, nfserr_exist, nfserr_xdev, nfserr_nodev,
+ nfserr_notdir, nfserr_isdir, nfserr_inval, nfserr_fbig,
+ nfserr_nospc, nfserr_rofs, nfserr_mlink,
+ nfserr_nametoolong, nfserr_notempty, nfserr_dquot, nfserr_stale,
+ nfserr_remote, nfserr_badhandle, nfserr_notsync,
+ nfserr_badcookie, nfserr_notsupp, nfserr_toosmall,
+ nfserr_serverfault, nfserr_badtype, nfserr_jukebox;
+
#ifdef NFSD_OPTIMIZE_SPACE
# define inline
@@ -52,18 +57,32 @@ nfsd_xdr_init(void)
nfserr_noent = htonl(NFSERR_NOENT);
nfserr_io = htonl(NFSERR_IO);
nfserr_inval = htonl(NFSERR_INVAL);
- nfserr_nxio = htonl(NFSERR_NXIO);
- nfserr_acces = htonl(NFSERR_ACCES);
- nfserr_exist = htonl(NFSERR_EXIST);
- nfserr_nodev = htonl(NFSERR_NODEV);
- nfserr_notdir = htonl(NFSERR_NOTDIR);
- nfserr_isdir = htonl(NFSERR_ISDIR);
- nfserr_fbig = htonl(NFSERR_FBIG);
- nfserr_nospc = htonl(NFSERR_NOSPC);
- nfserr_rofs = htonl(NFSERR_ROFS);
+ nfserr_nxio = htonl(NFSERR_NXIO);
+ nfserr_acces = htonl(NFSERR_ACCES);
+ nfserr_exist = htonl(NFSERR_EXIST);
+ nfserr_xdev = htonl(NFSERR_XDEV);
+ nfserr_nodev = htonl(NFSERR_NODEV);
+ nfserr_notdir = htonl(NFSERR_NOTDIR);
+ nfserr_isdir = htonl(NFSERR_ISDIR);
+ nfserr_inval = htonl(NFSERR_INVAL);
+ nfserr_fbig = htonl(NFSERR_FBIG);
+ nfserr_nospc = htonl(NFSERR_NOSPC);
+ nfserr_rofs = htonl(NFSERR_ROFS);
+ nfserr_mlink = htonl(NFSERR_MLINK);
nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
- nfserr_dquot = htonl(NFSERR_DQUOT);
- nfserr_stale = htonl(NFSERR_STALE);
+ nfserr_notempty = htonl(NFSERR_NOTEMPTY);
+ nfserr_dquot = htonl(NFSERR_DQUOT);
+ nfserr_stale = htonl(NFSERR_STALE);
+ nfserr_remote = htonl(NFSERR_REMOTE);
+ nfserr_badhandle = htonl(NFSERR_BADHANDLE);
+ nfserr_notsync = htonl(NFSERR_NOT_SYNC);
+ nfserr_badcookie = htonl(NFSERR_BAD_COOKIE);
+ nfserr_notsupp = htonl(NFSERR_NOTSUPP);
+ nfserr_toosmall = htonl(NFSERR_TOOSMALL);
+ nfserr_serverfault = htonl(NFSERR_SERVERFAULT);
+ nfserr_badtype = htonl(NFSERR_BADTYPE);
+ nfserr_jukebox = htonl(NFSERR_JUKEBOX);
+
inited = 1;
}
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 7e7eba9a9..69defe790 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -17,6 +17,7 @@
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
+#define __NO_VERSION__
#include <linux/module.h>
#include <linux/sunrpc/svc.h>
@@ -37,11 +38,12 @@ nfsd_proc_read(char *buffer, char **start, off_t offset, int count,
nfsdstats.rchits,
nfsdstats.rcmisses,
nfsdstats.rcnocache,
- nfsdstats.fh_cached,
- nfsdstats.fh_valid,
- nfsdstats.fh_fixup,
+ nfsdstats.fh_stale,
nfsdstats.fh_lookup,
- nfsdstats.fh_stale);
+ nfsdstats.fh_anon,
+ nfsdstats.fh_nocache_dir,
+ nfsdstats.fh_nocache_nondir);
+
/* Assume we haven't hit EOF yet. Will be set by svc_proc_read. */
*eof = 0;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 398d2ebae..2876b8455 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -32,6 +32,10 @@
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
+#ifdef CONFIG_NFSD_V3
+#include <linux/nfs3.h>
+#include <linux/nfsd/xdr3.h>
+#endif /* CONFIG_NFSD_V3 */
#include <linux/nfsd/nfsfh.h>
#include <linux/quotaops.h>
@@ -48,7 +52,12 @@
/* Hack until we have a macro check for mandatory locks. */
#ifndef IS_ISMNDLK
-#define IS_ISMNDLK(i) (((i)->i_mode & (S_ISGID|S_IXGRP)) == S_ISGID)
+/* We must ignore files (but only file) which might have mandatory
+ * locks on them because there is no way to know if the accesser has
+ * the lock.
+ */
+#define IS_ISMNDLK(i) (((i)->i_mode & (S_ISGID|S_IXGRP|S_IFMT)) \
+ == (S_ISGID|S_IFREG))
#endif
/* Check for dir entries '.' and '..' */
@@ -78,61 +87,46 @@ int nfsd_nservers = 0;
static struct raparms * raparml = NULL;
static struct raparms * raparm_cache = NULL;
+
+/*
+ * We need to do a check-parent every time
+ * after we have locked the parent - to verify
+ * that the parent is still our parent and
+ * that we are still hashed onto it..
+ *
+ * This is required in case two processes race
+ * on removing (or moving) the same entry: the
+ * parent lock will serialize them, but the
+ * other process will be too late..
+ *
+ * Note that this nfsd_check_parent is identical
+ * the check_parent in linux/fs/namei.c.
+ */
+#define nfsd_check_parent(dir, dentry) \
+ ((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
+
/*
* Lock a parent directory following the VFS locking protocol.
*/
int
fh_lock_parent(struct svc_fh *parent_fh, struct dentry *dchild)
{
- int nfserr = 0;
-
fh_lock(parent_fh);
/*
* Make sure the parent->child relationship still holds,
* and that the child is still hashed.
*/
- if (dchild->d_parent != parent_fh->fh_dentry)
- goto out_not_parent;
- if (list_empty(&dchild->d_hash))
- goto out_not_hashed;
-out:
- return nfserr;
+ if (nfsd_check_parent(parent_fh->fh_dentry, dchild))
+ return 0;
-out_not_parent:
- printk(KERN_WARNING
- "fh_lock_parent: %s/%s parent changed\n",
- dchild->d_parent->d_name.name, dchild->d_name.name);
- goto out_unlock;
-out_not_hashed:
printk(KERN_WARNING
- "fh_lock_parent: %s/%s unhashed\n",
+ "fh_lock_parent: %s/%s parent changed or child unhashed\n",
dchild->d_parent->d_name.name, dchild->d_name.name);
-out_unlock:
- nfserr = nfserr_noent;
- fh_unlock(parent_fh);
- goto out;
-}
-/*
- * Deny access to certain file systems
- */
-static inline int
-fs_off_limits(struct super_block *sb)
-{
- return !sb || sb->s_magic == NFS_SUPER_MAGIC
- || sb->s_magic == PROC_SUPER_MAGIC;
+ fh_unlock(parent_fh);
+ return nfserr_noent;
}
-/*
- * Check whether directory is a mount point, but it is all right if
- * this is precisely the local mount point being exported.
- */
-static inline int
-nfsd_iscovered(struct dentry *dentry, struct svc_export *exp)
-{
- return (dentry != dentry->d_covers &&
- dentry != exp->ex_dentry);
-}
/*
* Look up one component of a pathname.
@@ -169,12 +163,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
if (err)
goto out;
#endif
- err = nfserr_noent;
- if (fs_off_limits(dparent->d_sb))
- goto out;
err = nfserr_acces;
- if (nfsd_iscovered(dparent, exp))
- goto out;
/* Lookup the name, but don't follow links */
dchild = lookup_dentry(name, dget(dparent), 0);
@@ -250,6 +239,32 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
inode = dentry->d_inode;
err = inode_change_ok(inode, iap);
+ /* could be a "touch" (utimes) request where the user is not the owner but does
+ * have write permission. In this case the user should be allowed to set
+ * both times to the current time. We could just assume any such SETATTR
+ * is intended to set the times to "now", but we do a couple of simple tests
+ * to increase our confidence.
+ */
+#define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET)
+#define MAX_TOUCH_TIME_ERROR (30*60)
+ if (err
+ && (iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET
+ && iap->ia_mtime == iap->ia_ctime
+ ) {
+ /* looks good. now just make sure time is in the right ballpark.
+ * solaris, at least, doesn't seem to care what the time request is
+ */
+ time_t delta = iap->ia_atime - CURRENT_TIME;
+ if (delta<0) delta = -delta;
+ if (delta < MAX_TOUCH_TIME_ERROR) {
+ /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
+ * this will cause notify_change to setthese times to "now"
+ */
+ iap->ia_valid &= ~BOTH_TIME_SET;
+ err = inode_change_ok(inode, iap);
+ }
+ }
+
if (err)
goto out_nfserr;
@@ -321,6 +336,9 @@ printk("nfsd_setattr: size change??\n");
if (EX_ISSYNC(fhp->fh_export))
write_inode_now(inode);
err = 0;
+
+ /* Don't unlock inode; the nfssvc_release functions are supposed
+ * to do this. */
out:
return err;
@@ -329,6 +347,84 @@ out_nfserr:
goto out;
}
+#ifdef CONFIG_NFSD_V3
+/*
+ * Check server access rights to a file system object
+ */
+struct accessmap {
+ u32 access;
+ int how;
+};
+static struct accessmap nfs3_regaccess[] = {
+ { NFS3_ACCESS_READ, MAY_READ },
+ { NFS3_ACCESS_EXECUTE, MAY_EXEC },
+ { NFS3_ACCESS_MODIFY, MAY_WRITE|MAY_TRUNC },
+ { NFS3_ACCESS_EXTEND, MAY_WRITE },
+
+ { 0, 0 }
+};
+
+static struct accessmap nfs3_diraccess[] = {
+ { NFS3_ACCESS_READ, MAY_READ },
+ { NFS3_ACCESS_LOOKUP, MAY_EXEC },
+ { NFS3_ACCESS_MODIFY, MAY_EXEC|MAY_WRITE|MAY_TRUNC },
+ { NFS3_ACCESS_EXTEND, MAY_EXEC|MAY_WRITE },
+ { NFS3_ACCESS_DELETE, MAY_REMOVE },
+
+ { 0, 0 }
+};
+
+static struct accessmap nfs3_anyaccess[] = {
+ /* XXX: should we try to cover read/write here for clients that
+ * rely on us to do their access checking for special files? */
+
+ { 0, 0 }
+};
+
+int
+nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
+{
+ struct accessmap *map;
+ struct svc_export *export;
+ struct dentry *dentry;
+ u32 query, result = 0;
+ int error;
+
+ error = fh_verify(rqstp, fhp, 0, MAY_NOP);
+ if (error < 0)
+ goto out;
+
+ export = fhp->fh_export;
+ dentry = fhp->fh_dentry;
+
+ if (S_ISREG(dentry->d_inode->i_mode)) {
+ map = nfs3_regaccess;
+ } else if (S_ISDIR(dentry->d_inode->i_mode)) {
+ map = nfs3_diraccess;
+ } else {
+ map = nfs3_anyaccess;
+ }
+
+ query = *access;
+ while (map->access) {
+ if (map->access & query) {
+ error = nfsd_permission(export, dentry, map->how);
+ if (error == 0)
+ result |= map->access;
+ else if (error != -EPERM)
+ goto out;
+ }
+ map++;
+ }
+ *access = result;
+
+out:
+ return error;
+}
+#endif
+
+
+
/*
* Open an existing file or directory.
* The wflag argument indicates write access.
@@ -415,11 +511,28 @@ nfsd_close(struct file *filp)
/*
* Sync a file
+ * As this calls fsync (not fdatasync) there is no need for a write_inode
+ * after it.
*/
void
-nfsd_sync(struct inode *inode, struct file *filp)
+nfsd_sync(struct file *filp)
{
+ dprintk("nfsd: sync file %s\n", filp->f_dentry->d_name.name);
+ down(&filp->f_dentry->d_inode->i_sem);
filp->f_op->fsync(filp, filp->f_dentry);
+ up(&filp->f_dentry->d_inode->i_sem);
+}
+
+void
+nfsd_sync_dir(struct dentry *dp)
+{
+ struct inode *inode = dp->d_inode;
+ int (*fsync) (struct file *, struct dentry *);
+
+ if (inode->i_op->default_file_ops
+ && (fsync = inode->i_op->default_file_ops->fsync)) {
+ fsync(NULL, dp);
+ }
}
/*
@@ -550,11 +663,21 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
* Request sync writes if
* - the sync export option has been set, or
* - the client requested O_SYNC behavior (NFSv3 feature).
+ * - The file system doesn't support fsync().
* When gathered writes have been configured for this volume,
* flushing the data to disk is handled separately below.
*/
+#ifdef CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 2)
+ stable = EX_ISSYNC(exp);
+ else if (file.f_op->fsync == 0)
+ stable = 1;
+ if (stable && !EX_WGATHER(exp))
+ file.f_flags |= O_SYNC;
+#else
if ((stable || (stable = EX_ISSYNC(exp))) && !EX_WGATHER(exp))
file.f_flags |= O_SYNC;
+#endif /* CONFIG_NFSD_V3 */
file.f_pos = offset; /* set write offset */
@@ -574,7 +697,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
/* clear setuid/setgid flag after write */
if (err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID))) {
struct iattr ia;
- kernel_cap_t saved_cap;
+ kernel_cap_t saved_cap = 0;
ia.ia_valid = ATTR_MODE;
ia.ia_mode = inode->i_mode & ~(S_ISUID | S_ISGID);
@@ -609,6 +732,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
interruptible_sleep_on_timeout(&inode->i_wait, 10 * HZ / 1000);
#else
dprintk("nfsd: write defer %d\n", current->pid);
+/* FIXME: Olaf commented this out [gam3] */
schedule_timeout((HZ+99)/100);
dprintk("nfsd: write resume %d\n", current->pid);
#endif
@@ -616,15 +740,14 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (inode->i_state & I_DIRTY) {
dprintk("nfsd: write sync %d\n", current->pid);
- nfsd_sync(inode, &file);
- write_inode_now(inode);
+ nfsd_sync(&file);
}
wake_up(&inode->i_wait);
last_ino = inode->i_ino;
last_dev = inode->i_dev;
}
- dprintk("nfsd: write complete\n");
+ dprintk("nfsd: write complete err=%d\n", err);
if (err >= 0)
err = 0;
else
@@ -635,6 +758,36 @@ out:
return err;
}
+
+#ifdef CONFIG_NFSD_V3
+/*
+ * Commit all pendig writes to stable storage.
+ * Strictly speaking, we could sync just indicated the file region here,
+ * but there's currently no way we can ask the VFS to do so.
+ *
+ * We lock the file to make sure we return full WCC data to the client.
+ */
+int
+nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ off_t offset, unsigned long count)
+{
+ struct file file;
+ int err;
+
+ if ((err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_WRITE, &file)) != 0)
+ return err;
+
+ if (file.f_op && file.f_op->fsync) {
+ nfsd_sync(&file);
+ } else {
+ err = nfserr_notsupp;
+ }
+
+ nfsd_close(&file);
+ return err;
+}
+#endif /* CONFIG_NFSD_V3 */
+
/*
* Create a file (regular, directory, device, fifo); UNIX sockets
* not yet implemented.
@@ -672,6 +825,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
* If it has, the parent directory should already be locked.
*/
if (!resfhp->fh_dverified) {
+ /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
dchild = lookup_dentry(fname, dget(dentry), 0);
err = PTR_ERR(dchild);
if (IS_ERR(dchild))
@@ -682,20 +836,24 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (err)
goto out;
} else {
+ /* called from nfsd_proc_create */
dchild = resfhp->fh_dentry;
- if (!fhp->fh_locked)
+ if (!fhp->fh_locked) {
+ /* not actually possible */
printk(KERN_ERR
"nfsd_create: parent %s/%s not locked!\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
+ err = -EIO;
+ goto out;
+ }
}
/*
* Make sure the child dentry is still negative ...
*/
err = nfserr_exist;
if (dchild->d_inode) {
- printk(KERN_WARNING
- "nfsd_create: dentry %s/%s not negative!\n",
+ dprintk("nfsd_create: dentry %s/%s not negative!\n",
dentry->d_name.name, dchild->d_name.name);
goto out;
}
@@ -710,8 +868,6 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
break;
case S_IFDIR:
opfunc = (nfsd_dirop_t) dirp->i_op->mkdir;
- /* Odd, indeed, but filesystems did it anyway */
- iap->ia_mode &= (S_IRWXUGO|S_ISVTX) & ~current->fs->umask;
break;
case S_IFCHR:
case S_IFBLK:
@@ -725,12 +881,16 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
case S_IFSOCK:
opfunc = dirp->i_op->mknod;
break;
+ default:
+ printk("nfsd: bad file type %o in nfsd_create\n", type);
+ err = nfserr_inval;
}
if (!opfunc)
goto out;
if (!(iap->ia_valid & ATTR_MODE))
iap->ia_mode = 0;
+ iap->ia_mode = (iap->ia_mode & S_IALLUGO) | type;
/*
* Call the dir op function to create the object.
@@ -740,8 +900,10 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (err < 0)
goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(dirp);
+ if (EX_ISSYNC(fhp->fh_export)) {
+ nfsd_sync_dir(dentry);
+ write_inode_now(dchild->d_inode);
+ }
/*
* Update the file handle to get the new inode info.
@@ -764,6 +926,126 @@ out_nfserr:
goto out;
}
+#ifdef CONFIG_NFSD_V3
+/*
+ * NFSv3 version of nfsd_create
+ */
+int
+nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ char *fname, int flen, struct iattr *iap,
+ struct svc_fh *resfhp, int createmode, u32 *verifier)
+{
+ struct dentry *dentry, *dchild;
+ struct inode *dirp;
+ int err;
+
+ err = nfserr_perm;
+ if (!flen)
+ goto out;
+ if (!(iap->ia_valid & ATTR_MODE))
+ iap->ia_mode = 0;
+ err = fh_verify(rqstp, fhp, S_IFDIR, MAY_CREATE);
+ if (err)
+ goto out;
+
+ dentry = fhp->fh_dentry;
+ dirp = dentry->d_inode;
+
+ /* Get all the sanity checks out of the way before
+ * we lock the parent. */
+ err = nfserr_notdir;
+ if(!dirp->i_op || !dirp->i_op->lookup)
+ goto out;
+ err = nfserr_perm;
+ if(!dirp->i_op->create)
+ goto out;
+
+ /*
+ * Compose the response file handle.
+ */
+ dchild = lookup_dentry(fname, dget(dentry), 0);
+ err = PTR_ERR(dchild);
+ if(IS_ERR(dchild))
+ goto out_nfserr;
+ fh_compose(resfhp, fhp->fh_export, dchild);
+
+ /*
+ * We must lock the directory before we check for the inode.
+ */
+ err = fh_lock_parent(fhp, dchild);
+ if (err)
+ goto out;
+
+ if (dchild->d_inode) {
+ err = 0;
+
+ if (resfhp->fh_handle.fh_ino == 0)
+ /* inode might have been instantiated while we slept */
+ fh_update(resfhp);
+
+ switch (createmode) {
+ case NFS3_CREATE_UNCHECKED:
+ if (! S_ISREG(dchild->d_inode->i_mode))
+ err = nfserr_exist;
+ else {
+ iap->ia_valid &= ATTR_SIZE;
+ goto set_attr;
+ }
+ break;
+ case NFS3_CREATE_EXCLUSIVE:
+ if ( dchild->d_inode->i_mtime == verifier[0]
+ && dchild->d_inode->i_atime == verifier[1]
+ && dchild->d_inode->i_mode == S_IFREG
+ && dchild->d_inode->i_size == 0 )
+ break;
+ /* fallthru */
+ case NFS3_CREATE_GUARDED:
+ err = nfserr_exist;
+ }
+ goto out;
+ }
+
+ err = dirp->i_op->create(dirp, dchild, iap->ia_mode);
+ if (err < 0)
+ goto out_nfserr;
+
+ if (EX_ISSYNC(fhp->fh_export)) {
+ nfsd_sync_dir(dentry);
+ /* setattr will sync the child (or not) */
+ }
+
+ /*
+ * Update the filehandle to get the new inode info.
+ */
+ fh_update(resfhp);
+ err = 0;
+
+ if (createmode == NFS3_CREATE_EXCLUSIVE) {
+ /* Cram the verifier into atime/mtime */
+ iap->ia_valid = ATTR_MTIME|ATTR_ATIME|ATTR_MTIME_SET|ATTR_ATIME_SET;
+ iap->ia_mtime = verifier[0];
+ iap->ia_atime = verifier[1];
+ }
+
+ /* Set file attributes. Mode has already been set and
+ * setting uid/gid works only for root. Irix appears to
+ * send along the gid when it tries to implement setgid
+ * directories via NFS. Clear out all that cruft.
+ */
+ set_attr:
+ if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
+ err = nfsd_setattr(rqstp, resfhp, iap);
+
+ out:
+ fh_unlock(fhp);
+ return err;
+
+ out_nfserr:
+ err = nfserrno(-err);
+ goto out;
+}
+#endif /* CONFIG_NFSD_V3 */
+
/*
* Truncate a file.
* The calling routines must make sure to update the ctime
@@ -779,7 +1061,7 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
struct inode *inode;
struct iattr newattrs;
int err;
- kernel_cap_t saved_cap;
+ kernel_cap_t saved_cap = 0;
err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC);
if (err)
@@ -815,6 +1097,8 @@ nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
if (current->fsuid != 0)
current->cap_effective = saved_cap;
put_write_access(inode);
+ if (EX_ISSYNC(fhp->fh_export))
+ nfsd_sync_dir(dentry);
fh_unlock(fhp);
out_nfserr:
if (err)
@@ -848,7 +1132,10 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
goto out;
UPDATE_ATIME(inode);
- /* N.B. Why does this call need a get_fs()?? */
+ /* N.B. Why does this call need a get_fs()??
+ * Remove the set_fs and watch the fireworks:-) --okir
+ */
+
oldfs = get_fs(); set_fs(KERNEL_DS);
err = inode->i_op->readlink(dentry, buf, *lenp);
set_fs(oldfs);
@@ -873,7 +1160,8 @@ int
nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
char *fname, int flen,
char *path, int plen,
- struct svc_fh *resfhp)
+ struct svc_fh *resfhp,
+ struct iattr *iap)
{
struct dentry *dentry, *dnew;
struct inode *dirp;
@@ -889,8 +1177,6 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry;
err = nfserr_perm;
- if (nfsd_iscovered(dentry, fhp->fh_export))
- goto out;
dirp = dentry->d_inode;
if (!dirp->i_op || !dirp->i_op->symlink)
goto out;
@@ -913,7 +1199,16 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = dirp->i_op->symlink(dirp, dnew, path);
if (!err) {
if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(dirp);
+ nfsd_sync_dir(dentry);
+ if (iap) {
+ iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
+ if (iap->ia_valid) {
+ iap->ia_valid |= ATTR_CTIME;
+ err = notify_change(dnew, iap);
+ if (!err && EX_ISSYNC(fhp->fh_export))
+ write_inode_now(dentry->d_inode);
+ }
+ }
} else
err = nfserrno(-err);
}
@@ -945,7 +1240,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = fh_verify(rqstp, ffhp, S_IFDIR, MAY_CREATE);
if (err)
goto out;
- err = fh_verify(rqstp, tfhp, S_IFREG, MAY_NOP);
+ err = fh_verify(rqstp, tfhp, -S_IFDIR, MAY_NOP);
if (err)
goto out;
@@ -974,10 +1269,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
dold = tfhp->fh_dentry;
dest = dold->d_inode;
- err = nfserr_acces;
- if (nfsd_iscovered(ddir, ffhp->fh_export))
- goto out_unlock;
- /* FIXME: nxdev for NFSv3 */
+ err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
if (dirp->i_dev != dest->i_dev)
goto out_unlock;
@@ -991,7 +1283,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = dirp->i_op->link(dold, dirp, dnew);
if (!err) {
if (EX_ISSYNC(ffhp->fh_export)) {
- write_inode_now(dirp);
+ nfsd_sync_dir(ddir);
write_inode_now(dest);
}
} else
@@ -1010,29 +1302,12 @@ out_nfserr:
}
/*
- * We need to do a check-parent every time
- * after we have locked the parent - to verify
- * that the parent is still our parent and
- * that we are still hashed onto it..
- *
- * This is required in case two processes race
- * on removing (or moving) the same entry: the
- * parent lock will serialize them, but the
- * other process will be too late..
- *
- * Note that this nfsd_check_parent is different
- * than the one in linux/include/dcache_func.h.
- */
-#define nfsd_check_parent(dir, dentry) \
- ((dir) == (dentry)->d_parent->d_inode && !list_empty(&dentry->d_hash))
-
-/*
* This follows the model of double_lock() in the VFS.
*/
static inline void nfsd_double_down(struct semaphore *s1, struct semaphore *s2)
{
if (s1 != s2) {
- if ((unsigned long) s1 > (unsigned long) s2) {
+ if ((unsigned long) s1 < (unsigned long) s2) {
struct semaphore *tmp = s1;
s1 = s2;
s2 = tmp;
@@ -1074,6 +1349,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
tdentry = tfhp->fh_dentry;
tdir = tdentry->d_inode;
+ err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
+ if (fdir->i_dev != tdir->i_dev)
+ goto out;
+
/* N.B. We shouldn't need this ... dentry layer handles it */
err = nfserr_perm;
if (!flen || (fname[0] == '.' &&
@@ -1100,19 +1379,35 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
* Lock the parent directories.
*/
nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
+
+#ifdef CONFIG_NFSD_V3
+ /* Fill in the pre-op attr for the wcc data for both
+ * tdir and fdir
+ */
+ fill_pre_wcc(ffhp);
+ fill_pre_wcc(tfhp);
+#endif /* CONFIG_NFSD_V3 */
+
err = -ENOENT;
/* GAM3 check for parent changes after locking. */
- if (nfsd_check_parent(fdir, odentry) &&
- nfsd_check_parent(tdir, ndentry)) {
+ if (nfsd_check_parent(fdentry, odentry) &&
+ nfsd_check_parent(tdentry, ndentry)) {
err = vfs_rename(fdir, odentry, tdir, ndentry);
if (!err && EX_ISSYNC(tfhp->fh_export)) {
- write_inode_now(fdir);
- write_inode_now(tdir);
+ nfsd_sync_dir(tdentry);
+ nfsd_sync_dir(fdentry);
}
} else
dprintk("nfsd: Caught race in nfsd_rename");
+#ifdef CONFIG_NFSD_V3
+ /* Fill in the post-op attr for the wcc data for both
+ * tdir and fdir
+ */
+ fill_post_wcc(ffhp);
+ fill_post_wcc(tfhp);
+#endif /* CONFIG_NFSD_V3 */
nfsd_double_up(&tdir->i_sem, &fdir->i_sem);
dput(ndentry);
@@ -1182,18 +1477,23 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
rdentry->d_count++;
nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
- if (!fhp->fh_pre_mtime)
- fhp->fh_pre_mtime = dirp->i_mtime;
+
+#ifdef CONFIG_NFSD_V3
+ fill_pre_wcc(fhp);
+#else
fhp->fh_locked = 1;
+#endif /* CONFIG_NFSD_V3 */
err = -ENOENT;
- if (nfsd_check_parent(dirp, rdentry))
+ if (nfsd_check_parent(dentry, rdentry))
err = vfs_rmdir(dirp, rdentry);
rdentry->d_count--;
- if (!fhp->fh_post_version)
- fhp->fh_post_version = dirp->i_version;
+#ifdef CONFIG_NFSD_V3
+ fill_post_wcc(fhp);
+#else
fhp->fh_locked = 0;
+#endif /* CONFIG_NFSD_V3 */
nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);
dput(rdentry);
@@ -1201,8 +1501,11 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if (err)
goto out_nfserr;
- if (EX_ISSYNC(fhp->fh_export))
- write_inode_now(dirp);
+ if (EX_ISSYNC(fhp->fh_export)) {
+ down(&dentry->d_inode->i_sem);
+ nfsd_sync_dir(dentry);
+ up(&dentry->d_inode->i_sem);
+ }
out:
return err;
@@ -1213,10 +1516,11 @@ out_nfserr:
/*
* Read entries from a directory.
+ * The verifier is an NFSv3 thing we ignore for now.
*/
int
nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
- encode_dent_fn func, u32 *buffer, int *countp)
+ encode_dent_fn func, u32 *buffer, int *countp, u32 *verf)
{
struct inode *inode;
u32 *p;
@@ -1242,6 +1546,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
cd.rqstp = rqstp;
cd.buffer = buffer;
cd.buflen = *countp; /* count of words */
+ cd.dirfh = fhp;
/*
* Read the directory entries. This silly loop is necessary because
@@ -1271,8 +1576,14 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
/* If we didn't fill the buffer completely, we're at EOF */
eof = !cd.eob;
- if (cd.offset)
- *cd.offset = htonl(file.f_pos);
+ if (cd.offset) {
+#ifdef CONFIG_NFSD_V3
+ if (rqstp->rq_vers == 3)
+ (void)enc64(cd.offset, file.f_pos);
+ else
+#endif /* CONFIG_NFSD_V3 */
+ *cd.offset = htonl(file.f_pos);
+ }
p = cd.buffer;
*p++ = 0; /* no more entries */
@@ -1334,7 +1645,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
{
struct inode *inode = dentry->d_inode;
int err;
- kernel_cap_t saved_cap;
+ kernel_cap_t saved_cap = 0;
if (acc == MAY_NOP)
return 0;
@@ -1353,17 +1664,10 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
dprintk(" owner %d/%d user %d/%d\n",
inode->i_uid, inode->i_gid, current->fsuid, current->fsgid);
#endif
-#ifndef CONFIG_NFSD_SUN
- if (dentry->d_mounts != dentry) {
- return nfserr_perm;
- }
-#endif
if (acc & (MAY_WRITE | MAY_SATTR | MAY_TRUNC)) {
if (EX_RDONLY(exp) || IS_RDONLY(inode))
return nfserr_rofs;
- if (S_ISDIR(inode->i_mode) && nfsd_iscovered(dentry, exp))
- return nfserr_perm;
if (/* (acc & MAY_WRITE) && */ IS_IMMUTABLE(inode))
return nfserr_perm;
}
diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c
index 40d5d6c2c..c1ea11ff8 100644
--- a/fs/nls/nls_base.c
+++ b/fs/nls/nls_base.c
@@ -4,6 +4,8 @@
* Native language support--charsets and unicode translations.
* By Gordon Chaffee 1996, 1997
*
+ * Unicode based case conversion 1999 by Wolfram Pienkoss
+ *
*/
#include <linux/version.h>
@@ -363,6 +365,78 @@ static unsigned char *page_uni2charset[256] = {
page00
};
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2upper[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
void inc_use_count(void)
{
@@ -376,6 +450,8 @@ static struct nls_table default_table = {
"default",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp437.c b/fs/nls/nls_cp437.c
index 46a5621b1..a64a12d4b 100644
--- a/fs/nls/nls_cp437.c
+++ b/fs/nls/nls_cp437.c
@@ -355,7 +355,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -369,15 +404,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0x00, 0x8e, 0x00, 0x8f, 0x80, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x90, 0x92, 0x92, 0x00, 0x99, 0x00, 0x00, 0x00, /* 0x90-0x97 */
0x00, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -385,12 +421,11 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -407,6 +442,8 @@ static struct nls_table table = {
"cp437",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp737.c b/fs/nls/nls_cp737.c
index 6b34b38bd..0ae5575e0 100644
--- a/fs/nls/nls_cp737.c
+++ b/fs/nls/nls_cp737.c
@@ -283,7 +283,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x80-0x87 */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x88-0x8f */
+ 0xa8, 0xa9, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xe0, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xe1, 0xe2, 0xe3, 0xe5, 0xe6, 0xe7, /* 0xe8-0xef */
+ 0xe9, 0xf1, 0xf2, 0xf3, 0xe4, 0xe8, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -297,28 +332,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x98-0x9f */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0xa0-0xa7 */
+ 0x90, 0x91, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0x97, 0xea, 0xeb, 0xec, 0xf4, 0xed, 0xee, 0xef, /* 0xe0-0xe7 */
+ 0xf5, 0xf0, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -335,6 +370,8 @@ static struct nls_table table = {
"cp737",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp775.c b/fs/nls/nls_cp775.c
index 4c11d63ff..d740adbba 100644
--- a/fs/nls/nls_cp775.c
+++ b/fs/nls/nls_cp775.c
@@ -283,7 +283,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8b, 0x8b, 0x8c, 0xa5, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x85, 0x96, 0x98, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x83, 0x8c, 0xa2, 0xa4, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0x88, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xd0, 0xd1, 0xd2, /* 0xb0-0xb7 */
+ 0xd3, 0xb9, 0xba, 0xbb, 0xbc, 0xd4, 0xd5, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xd6, 0xd7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xd8, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xa2, 0xe1, 0x93, 0xe7, 0xe4, 0xe4, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe9, 0xe9, 0xeb, 0xeb, 0xec, 0x89, 0xec, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -297,28 +332,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0x00, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0xa0, 0x8e, 0x95, 0x8f, 0x80, /* 0x80-0x87 */
+ 0xad, 0xed, 0x8a, 0x8a, 0xa1, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x92, 0x92, 0xe2, 0x99, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x97, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xe0, 0xa3, 0xa3, 0x8d, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
- 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0x00, 0xea, 0x00, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xbd, 0xbe, 0xc6, 0xc7, /* 0xd0-0xd7 */
+ 0xcf, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0x00, 0xe3, /* 0xe0-0xe7 */
+ 0xe8, 0xe8, 0xea, 0xea, 0xee, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -335,6 +370,8 @@ static struct nls_table table = {
"cp775",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp850.c b/fs/nls/nls_cp850.c
index c93b99c9b..d15cfd893 100644
--- a/fs/nls/nls_cp850.c
+++ b/fs/nls/nls_cp850.c
@@ -247,7 +247,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xa0, 0x83, 0x85, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd0, 0x88, 0x89, 0x8a, 0xd5, 0xa1, 0x8c, /* 0xd0-0xd7 */
+ 0x8b, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x8d, 0xdf, /* 0xd8-0xdf */
+ 0xa2, 0xe1, 0x93, 0x95, 0xe4, 0xe4, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe7, 0xa3, 0x96, 0x97, 0xec, 0xec, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -261,28 +296,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
- 0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xb7, 0x8f, 0x80, /* 0x80-0x87 */
+ 0xd2, 0xd3, 0xd4, 0xd8, 0xd7, 0xde, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x92, 0x92, 0xe2, 0x99, 0xe3, 0xea, 0xeb, /* 0x90-0x97 */
+ 0x00, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+ 0xb5, 0xd6, 0xe0, 0xe9, 0xa5, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0x49, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0xeb, 0x00, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0x00, 0xe8, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xed, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -299,6 +334,8 @@ static struct nls_table table = {
"cp850",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp852.c b/fs/nls/nls_cp852.c
index 1a1385936..f270943ff 100644
--- a/fs/nls/nls_cp852.c
+++ b/fs/nls/nls_cp852.c
@@ -247,7 +247,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8b, 0x8b, 0x8c, 0xab, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x92, 0x92, 0x93, 0x94, 0x96, 0x96, 0x98, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9c, 0x9c, 0x88, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa7, 0xa7, /* 0xa0-0xa7 */
+ 0xa9, 0xa9, 0xaa, 0xab, 0x9f, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xa0, 0x83, 0xd8, /* 0xb0-0xb7 */
+ 0xad, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd0, 0xd4, 0x89, 0xd4, 0xe5, 0xa1, 0x8c, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xee, 0x85, 0xdf, /* 0xd8-0xdf */
+ 0xa2, 0xe1, 0x93, 0xe4, 0xe4, 0xe5, 0xe7, 0xe7, /* 0xe0-0xe7 */
+ 0xea, 0xa3, 0xea, 0xfb, 0xec, 0xec, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfd, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -261,28 +296,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x8a, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x00, 0x00, 0x00, 0x95, 0x00, 0x97, /* 0x90-0x97 */
- 0x00, 0x99, 0x9a, 0x9b, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0x00, /* 0xa0-0xa7 */
- 0xa8, 0x00, 0xaa, 0x00, 0xac, 0x00, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xde, 0x8f, 0x80, /* 0x80-0x87 */
+ 0x9d, 0xd3, 0x8a, 0x8a, 0xd7, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x91, 0xe2, 0x99, 0x95, 0x95, 0x97, /* 0x90-0x97 */
+ 0x97, 0x99, 0x9a, 0x9b, 0x9b, 0x9d, 0x9e, 0xac, /* 0x98-0x9f */
+ 0xb5, 0xd6, 0xe0, 0xe9, 0xa4, 0xa4, 0xa6, 0xa6, /* 0xa0-0xa7 */
+ 0xa8, 0xa8, 0xaa, 0x8d, 0xac, 0xb8, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0x00, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, /* 0xc0-0xc7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0x00, 0xd1, 0xd2, 0xd3, 0x00, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0xe0, 0x00, 0xe2, 0xe3, 0x00, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0x00, 0xef, /* 0xe8-0xef */
+ 0xd1, 0xd1, 0xd2, 0xd3, 0xd2, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xb7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe3, 0xd5, 0xe6, 0xe6, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xe8, 0xeb, 0xed, 0xed, 0xdd, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0x00, 0xfc, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xeb, 0xfc, 0xfc, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -299,6 +334,8 @@ static struct nls_table table = {
"cp852",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp855.c b/fs/nls/nls_cp855.c
index 7c1c06d0d..c0b6eb7fc 100644
--- a/fs/nls/nls_cp855.c
+++ b/fs/nls/nls_cp855.c
@@ -247,7 +247,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, NULL, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x80, 0x82, 0x82, 0x84, 0x84, 0x86, 0x86, /* 0x80-0x87 */
+ 0x88, 0x88, 0x8a, 0x8a, 0x8c, 0x8c, 0x8e, 0x8e, /* 0x88-0x8f */
+ 0x90, 0x90, 0x92, 0x92, 0x94, 0x94, 0x96, 0x96, /* 0x90-0x97 */
+ 0x98, 0x98, 0x9a, 0x9a, 0x9c, 0x9c, 0x9e, 0x9e, /* 0x98-0x9f */
+ 0xa0, 0xa0, 0xa2, 0xa2, 0xa4, 0xa4, 0xa6, 0xa6, /* 0xa0-0xa7 */
+ 0xa8, 0xa8, 0xaa, 0xaa, 0xac, 0xac, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5, 0xb7, /* 0xb0-0xb7 */
+ 0xb7, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd0, 0xd2, 0xd2, 0xd4, 0xd4, 0xd6, 0xd6, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xd8, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xde, 0xe1, 0xe1, 0xe3, 0xe3, 0xe5, 0xe5, 0xe7, /* 0xe0-0xe7 */
+ 0xe7, 0xe9, 0xe9, 0xeb, 0xeb, 0xed, 0xed, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf1, 0xf3, 0xf3, 0xf5, 0xf5, 0xf7, /* 0xf0-0xf7 */
+ 0xf7, 0xf9, 0xf9, 0xfb, 0xfb, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -261,28 +296,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x00, 0x81, 0x00, 0x83, 0x00, 0x85, 0x00, 0x87, /* 0x80-0x87 */
- 0x00, 0x89, 0x00, 0x8b, 0x00, 0x8d, 0x00, 0x8f, /* 0x88-0x8f */
- 0x00, 0x91, 0x00, 0x93, 0x00, 0x95, 0x00, 0x97, /* 0x90-0x97 */
- 0x00, 0x99, 0x00, 0x9b, 0x00, 0x9d, 0x00, 0x9f, /* 0x98-0x9f */
- 0x00, 0xa1, 0x00, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */
- 0x00, 0xa9, 0x00, 0xab, 0x00, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0x00, /* 0xb0-0xb7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0x00, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x81, 0x81, 0x83, 0x83, 0x85, 0x85, 0x87, 0x87, /* 0x80-0x87 */
+ 0x89, 0x89, 0x8b, 0x8b, 0x8d, 0x8d, 0x8f, 0x8f, /* 0x88-0x8f */
+ 0x91, 0x91, 0x93, 0x93, 0x95, 0x95, 0x97, 0x97, /* 0x90-0x97 */
+ 0x99, 0x99, 0x9b, 0x9b, 0x9d, 0x9d, 0x9f, 0x9f, /* 0x98-0x9f */
+ 0xa1, 0xa1, 0xa3, 0xa3, 0xa5, 0xa5, 0xa7, 0xa7, /* 0xa0-0xa7 */
+ 0xa9, 0xa9, 0xab, 0xab, 0xad, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb6, 0xb6, 0xb8, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0x00, 0xd1, 0x00, 0xd3, 0x00, 0xd5, 0x00, 0xd7, /* 0xd0-0xd7 */
- 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
- 0xe0, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0x00, 0xea, 0x00, 0xec, 0x00, 0xee, 0xef, /* 0xe8-0xef */
- 0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
- 0xf8, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xd1, 0xd1, 0xd3, 0xd3, 0xd5, 0xd5, 0xd7, 0xd7, /* 0xd0-0xd7 */
+ 0xdd, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xe0, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe2, 0xe2, 0xe4, 0xe4, 0xe6, 0xe6, 0xe8, /* 0xe0-0xe7 */
+ 0xe8, 0xea, 0xea, 0xec, 0xec, 0xee, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf2, 0xf2, 0xf4, 0xf4, 0xf6, 0xf6, 0xf8, /* 0xf0-0xf7 */
+ 0xf8, 0xfa, 0xfa, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -299,6 +334,8 @@ static struct nls_table table = {
"cp855",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp857.c b/fs/nls/nls_cp857.c
index b3007525a..8125401f1 100644
--- a/fs/nls/nls_cp857.c
+++ b/fs/nls/nls_cp857.c
@@ -211,7 +211,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x69, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9f, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa7, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xa0, 0x83, 0x85, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0x88, 0x89, 0x8a, 0x00, 0xa1, 0x8c, /* 0xd0-0xd7 */
+ 0x8b, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xec, 0xdf, /* 0xd8-0xdf */
+ 0xa2, 0xe1, 0x93, 0x95, 0xe4, 0xe4, 0xe6, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xa3, 0x96, 0x97, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -225,28 +260,28 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0x00, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0xb6, 0x8e, 0xb7, 0x8f, 0x80, /* 0x80-0x87 */
+ 0xd2, 0xd3, 0xd4, 0xd8, 0xd7, 0x49, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x92, 0x92, 0xe2, 0x99, 0xe3, 0xea, 0xeb, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x9e, /* 0x98-0x9f */
+ 0xb5, 0xd6, 0xe0, 0xe9, 0xa5, 0xa5, 0xa6, 0xa6, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0x00, 0xc7, /* 0xc0-0xc7 */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc7, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0xe0, 0x00, 0xe2, 0xe3, 0x00, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0xeb, 0x00, 0x00, 0xee, 0xef, /* 0xe8-0xef */
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe5, 0xe5, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xde, 0x00, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -263,6 +298,8 @@ static struct nls_table table = {
"cp857",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp860.c b/fs/nls/nls_cp860.c
index af1ee2358..187187f24 100644
--- a/fs/nls/nls_cp860.c
+++ b/fs/nls/nls_cp860.c
@@ -319,7 +319,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0xa0, 0x87, /* 0x80-0x87 */
+ 0x88, 0x88, 0x8a, 0xa1, 0x93, 0x8d, 0x84, 0x83, /* 0x88-0x8f */
+ 0x82, 0x85, 0x8a, 0x93, 0x94, 0x95, 0xa3, 0x97, /* 0x90-0x97 */
+ 0x8d, 0x94, 0x81, 0x9b, 0x9c, 0x97, 0x9e, 0xa2, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0x95, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -333,15 +368,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, /* 0x80-0x87 */
- 0x00, 0x89, 0x00, 0x8b, 0x8c, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x96, 0x00, /* 0x90-0x97 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0x8f, 0x8e, 0x91, 0x86, 0x80, /* 0x80-0x87 */
+ 0x89, 0x89, 0x92, 0x8b, 0x8c, 0x98, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x8c, 0x99, 0xa9, 0x96, 0x9d, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x86, 0x8b, 0x9f, 0x96, 0xa5, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -349,12 +385,11 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -371,6 +406,8 @@ static struct nls_table table = {
"cp860",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp861.c b/fs/nls/nls_cp861.c
index bdb085abf..d42259d0a 100644
--- a/fs/nls/nls_cp861.c
+++ b/fs/nls/nls_cp861.c
@@ -355,7 +355,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8c, 0x8c, 0x95, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x98, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa0, 0xa1, 0xa2, 0xa3, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -369,15 +404,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x00, 0x8b, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x97, /* 0x90-0x97 */
- 0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0x00, 0x8e, 0x00, 0x8f, 0x80, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x8b, 0x8b, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x92, 0x92, 0x00, 0x99, 0x8d, 0x00, 0x97, /* 0x90-0x97 */
+ 0x97, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+ 0xa4, 0xa5, 0xa6, 0xa7, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -385,12 +421,11 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
static void inc_use_count(void)
@@ -407,6 +442,8 @@ static struct nls_table table = {
"cp861",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp862.c b/fs/nls/nls_cp862.c
index b0c7a49b4..6a86e5ef5 100644
--- a/fs/nls/nls_cp862.c
+++ b/fs/nls/nls_cp862.c
@@ -391,7 +391,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -405,15 +440,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -421,12 +457,12 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -442,6 +478,8 @@ static struct nls_table table = {
"cp862",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp863.c b/fs/nls/nls_cp863.c
index cea3d163d..06e5361bc 100644
--- a/fs/nls/nls_cp863.c
+++ b/fs/nls/nls_cp863.c
@@ -355,7 +355,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x83, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x85, 0x8f, /* 0x88-0x8f */
+ 0x82, 0x8a, 0x88, 0x93, 0x89, 0x8b, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x93, 0x81, 0x9b, 0x9c, 0x97, 0x96, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x8c, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -369,13 +404,14 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x84, 0x00, 0x86, 0x00, /* 0x80-0x87 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x94, 0x95, 0x00, 0x00, /* 0x90-0x97 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0x84, 0x84, 0x8e, 0x86, 0x80, /* 0x80-0x87 */
+ 0x92, 0x94, 0x91, 0x95, 0xa8, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x99, 0x94, 0x95, 0x9e, 0x9d, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
@@ -385,12 +421,12 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -406,6 +442,8 @@ static struct nls_table table = {
"cp863",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp864.c b/fs/nls/nls_cp864.c
index 972c728bd..6f3182aec 100644
--- a/fs/nls/nls_cp864.c
+++ b/fs/nls/nls_cp864.c
@@ -346,7 +346,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, pagefe, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -360,15 +395,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x00, 0x91, 0x00, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x00, 0x00, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -379,9 +415,9 @@ static unsigned char charset2upper[256] = {
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -397,6 +433,8 @@ static struct nls_table table = {
"cp864",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp865.c b/fs/nls/nls_cp865.c
index c68127450..24dd1dabb 100644
--- a/fs/nls/nls_cp865.c
+++ b/fs/nls/nls_cp865.c
@@ -355,7 +355,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x87, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x84, 0x86, /* 0x88-0x8f */
+ 0x82, 0x91, 0x91, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x94, 0x81, 0x9b, 0x9c, 0x9b, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0x00, 0xe3, 0xe5, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xed, 0x00, 0x00, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -369,15 +404,16 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x9a, 0x90, 0x00, 0x8e, 0x00, 0x8f, 0x80, /* 0x80-0x87 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
- 0x00, 0x99, 0x9a, 0x00, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x90, 0x92, 0x92, 0x00, 0x99, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x99, 0x9a, 0x9d, 0x9c, 0x9d, 0x9e, 0x00, /* 0x98-0x9f */
+ 0x00, 0x00, 0x00, 0x00, 0xa5, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
@@ -385,12 +421,12 @@ static unsigned char charset2upper[256] = {
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0xe2, 0x00, 0xe4, 0x00, 0xe6, 0x00, /* 0xe0-0xe7 */
- 0xe8, 0xe9, 0xea, 0x00, 0xec, 0x00, 0x00, 0xef, /* 0xe8-0xef */
+ 0x00, 0xe1, 0xe2, 0x00, 0xe4, 0xe4, 0x00, 0x00, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0x00, 0xec, 0xe8, 0x00, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -406,6 +442,8 @@ static struct nls_table table = {
"cp865",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp866.c b/fs/nls/nls_cp866.c
index d54824704..b78dd5148 100644
--- a/fs/nls/nls_cp866.c
+++ b/fs/nls/nls_cp866.c
@@ -283,7 +283,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, page22, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0x80-0x87 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0x88-0x8f */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0x90-0x97 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf1, 0xf1, 0xf3, 0xf3, 0xf5, 0xf5, 0xf7, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -297,28 +332,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0xa0-0xa7 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0xf0, 0x00, 0xf2, 0x00, 0xf4, 0x00, 0xf6, 0x00, /* 0xf0-0xf7 */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0xe0-0xe7 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0xe8-0xef */
+ 0xf0, 0xf0, 0xf2, 0xf2, 0xf4, 0xf4, 0xf6, 0xf6, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -334,6 +370,8 @@ static struct nls_table table = {
"cp866",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp869.c b/fs/nls/nls_cp869.c
index 586fb9936..76a693299 100644
--- a/fs/nls/nls_cp869.c
+++ b/fs/nls/nls_cp869.c
@@ -247,7 +247,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9b, 0x00, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x9d, 0x8e, 0x9e, /* 0x88-0x8f */
+ 0x9f, 0xa0, 0xa2, 0x00, 0x00, 0xa3, 0xfb, 0x97, /* 0x90-0x97 */
+ 0xfd, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xd6, 0xd7, 0xd8, 0xdd, /* 0xa0-0xa7 */
+ 0xde, 0xe0, 0xe1, 0xab, 0xe2, 0xe3, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xe4, 0xe5, 0xe6, /* 0xb0-0xb7 */
+ 0xe7, 0xb9, 0xba, 0xbb, 0xbc, 0xe8, 0xe9, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xea, 0xeb, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xec, /* 0xc8-0xcf */
+ 0xee, 0xf2, 0xf3, 0xf4, 0xf6, 0xfa, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -261,28 +296,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x00, 0x9c, 0x00, 0x00, 0x00, /* 0x98-0x9f */
- 0x00, 0x00, 0x00, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x90, 0x91, 0x92, 0x00, 0x00, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x86, 0x9c, 0x8d, 0x8f, 0x90, /* 0x98-0x9f */
+ 0x91, 0xa1, 0x92, 0x95, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0x00, 0x00, /* 0xd0-0xd7 */
- 0x00, 0xd9, 0xda, 0xdb, 0xdc, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, /* 0xe8-0xef */
- 0xf0, 0xf1, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xa4, 0xa5, /* 0xd0-0xd7 */
+ 0xa6, 0xd9, 0xda, 0xdb, 0xdc, 0xa7, 0xa8, 0xdf, /* 0xd8-0xdf */
+ 0xa9, 0xaa, 0xac, 0xad, 0xb5, 0xb6, 0xb7, 0xb8, /* 0xe0-0xe7 */
+ 0xbd, 0xbe, 0xc6, 0xc7, 0xcf, 0xcf, 0xd0, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xd1, 0xd2, 0xd3, 0xf5, 0xd4, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xd5, 0x96, 0xfc, 0x98, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -298,6 +334,8 @@ static struct nls_table table = {
"cp869",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_cp874.c b/fs/nls/nls_cp874.c
index b2c35c843..108a7045e 100644
--- a/fs/nls/nls_cp874.c
+++ b/fs/nls/nls_cp874.c
@@ -211,7 +211,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -225,14 +260,15 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
@@ -240,13 +276,13 @@ static unsigned char charset2upper[256] = {
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -262,6 +298,8 @@ static struct nls_table table = {
"cp874",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-1.c b/fs/nls/nls_iso8859-1.c
index 94ff9c39c..070d97920 100644
--- a/fs/nls/nls_iso8859-1.c
+++ b/fs/nls/nls_iso8859-1.c
@@ -135,7 +135,42 @@ static unsigned char *page_uni2charset[256] = {
page00, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -149,28 +184,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -186,6 +222,8 @@ static struct nls_table table = {
"iso8859-1",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-14.c b/fs/nls/nls_iso8859-14.c
index b466a6560..7cbd8c316 100644
--- a/fs/nls/nls_iso8859-14.c
+++ b/fs/nls/nls_iso8859-14.c
@@ -219,6 +219,79 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa2, 0xa2, 0xa3, 0xab, 0xab, 0xab, 0xa7, /* 0xa0-0xa7 */
+ 0xb8, 0xa9, 0xba, 0xab, 0xbc, 0xad, 0xae, 0xff, /* 0xa8-0xaf */
+ 0xb1, 0xb1, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb9, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbf, 0xbc, 0xbe, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2upper[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa1, 0xa3, 0xa6, 0xa6, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xa6, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb0, 0xb2, 0xb2, 0xb4, 0xb4, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xa8, 0xb7, 0xaa, 0xbb, 0xac, 0xbd, 0xbd, 0xbb, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xaf, /* 0xf8-0xff */
+};
+
+
static void inc_use_count(void)
{
MOD_INC_USE_COUNT;
@@ -233,6 +306,8 @@ static struct nls_table table = {
"iso8859-14",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-15.c b/fs/nls/nls_iso8859-15.c
index 33478bf9b..1376d1f4a 100644
--- a/fs/nls/nls_iso8859-15.c
+++ b/fs/nls/nls_iso8859-15.c
@@ -212,6 +212,79 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb8, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbd, 0xbd, 0xff, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char charset2upper[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+ 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa6, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb4, 0xb9, 0xba, 0xbb, 0xbc, 0xbc, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xbe, /* 0xf8-0xff */
+};
+
+
static void inc_use_count(void)
{
MOD_INC_USE_COUNT;
@@ -226,6 +299,8 @@ static struct nls_table table = {
"iso8859-15",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-2.c b/fs/nls/nls_iso8859-2.c
index 8349b879a..274a717c9 100644
--- a/fs/nls/nls_iso8859-2.c
+++ b/fs/nls/nls_iso8859-2.c
@@ -207,7 +207,42 @@ static unsigned char *page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xb1, 0xa2, 0xb3, 0xa4, 0xb5, 0xb6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xb9, 0xba, 0xbb, 0xbc, 0xad, 0xbe, 0xbf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -221,28 +256,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0x00, 0xb2, 0x00, 0xb4, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+ 0xb0, 0xa1, 0xb2, 0xa3, 0xb4, 0xa5, 0xa6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xa9, 0xaa, 0xab, 0xac, 0xbd, 0xae, 0xaf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -258,6 +294,8 @@ static struct nls_table table = {
"iso8859-2",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-3.c b/fs/nls/nls_iso8859-3.c
index 23af5447b..34eebad93 100644
--- a/fs/nls/nls_iso8859-3.c
+++ b/fs/nls/nls_iso8859-3.c
@@ -207,7 +207,42 @@ static unsigned char *page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xb1, 0xa2, 0xa3, 0xa4, 0x00, 0xb6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0x69, 0xba, 0xbb, 0xbc, 0xad, 0x00, 0xbf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0x00, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0x00, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -221,28 +256,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0x00, 0xb2, 0xb3, 0xb4, 0xb5, 0x00, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xa1, 0xb2, 0xb3, 0xb4, 0x00, 0xa6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0x49, 0xaa, 0xab, 0xac, 0xbd, 0x00, 0xaf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0xe3, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0x00, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0x00, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -258,6 +294,8 @@ static struct nls_table table = {
"iso8859-3",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-4.c b/fs/nls/nls_iso8859-4.c
index abbe1bd9b..18ef00e49 100644
--- a/fs/nls/nls_iso8859-4.c
+++ b/fs/nls/nls_iso8859-4.c
@@ -207,7 +207,42 @@ static unsigned char *page_uni2charset[256] = {
page00, page01, page02, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xb1, 0xa2, 0xb3, 0xa4, 0xb5, 0xb6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xb9, 0xba, 0xbb, 0xbc, 0xad, 0xbe, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbf, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -221,28 +256,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0x00, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0x00, 0xb2, 0x00, 0xb4, 0x00, 0x00, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0x00, 0x00, 0x00, 0x00, 0xbd, 0x00, 0x00, /* 0xb8-0xbf */
+ 0xb0, 0xa1, 0xb2, 0xa3, 0xb4, 0xa5, 0xa6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xa9, 0xaa, 0xab, 0xac, 0xbd, 0xae, 0xbd, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -258,6 +294,8 @@ static struct nls_table table = {
"iso8859-4",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-5.c b/fs/nls/nls_iso8859-5.c
index 1fe18003f..2ba940d78 100644
--- a/fs/nls/nls_iso8859-5.c
+++ b/fs/nls/nls_iso8859-5.c
@@ -211,7 +211,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, page21, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xa0-0xa7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xad, 0xfe, 0xff, /* 0xa8-0xaf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xb0-0xb7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -225,28 +260,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xd0-0xd7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xf0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xf0-0xf7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xfd, 0xae, 0xaf, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -262,6 +298,8 @@ static struct nls_table table = {
"iso8859-5",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-6.c b/fs/nls/nls_iso8859-6.c
index 7ed46f426..78b0203cf 100644
--- a/fs/nls/nls_iso8859-6.c
+++ b/fs/nls/nls_iso8859-6.c
@@ -171,7 +171,42 @@ static unsigned char *page_uni2charset[256] = {
page00, NULL, NULL, NULL, NULL, NULL, page06, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+ 0x00, 0x00, 0x00, 0x00, 0xac, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */
+ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -185,28 +220,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+ 0x00, 0x00, 0x00, 0x00, 0xac, 0xad, 0x00, 0x00, /* 0xa8-0xaf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */
+ 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xd8, 0xd9, 0xda, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
- 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf0, 0xf1, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -222,6 +258,8 @@ static struct nls_table table = {
"iso8859-6",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-7.c b/fs/nls/nls_iso8859-7.c
index 180ac239b..a21a56d03 100644
--- a/fs/nls/nls_iso8859-7.c
+++ b/fs/nls/nls_iso8859-7.c
@@ -247,7 +247,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xdc, 0xb7, /* 0xb0-0xb7 */
+ 0xdd, 0xde, 0xdf, 0xbb, 0xfc, 0xbd, 0xfd, 0xfe, /* 0xb8-0xbf */
+ 0xc0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0x00, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0x00, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -261,28 +296,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
- 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0x00, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0x00, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, /* 0xf8-0xff */
+ 0xd0, 0xd1, 0x00, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xb6, 0xb8, 0xb9, 0xba, /* 0xd8-0xdf */
+ 0xe0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd3, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xbc, 0xbe, 0xbf, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -298,6 +334,8 @@ static struct nls_table table = {
"iso8859-7",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-8.c b/fs/nls/nls_iso8859-8.c
index 054f5a4a8..c8282dad3 100644
--- a/fs/nls/nls_iso8859-8.c
+++ b/fs/nls/nls_iso8859-8.c
@@ -211,7 +211,42 @@ static unsigned char *page_uni2charset[256] = {
page20, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -225,28 +260,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0x00, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
- 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
- 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
- 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0x00, /* 0xb8-0xbf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
- 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+ 0xf8, 0xf9, 0xfa, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -262,6 +298,8 @@ static struct nls_table table = {
"iso8859-8",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_iso8859-9.c b/fs/nls/nls_iso8859-9.c
index eaa8c4c68..74baa761e 100644
--- a/fs/nls/nls_iso8859-9.c
+++ b/fs/nls/nls_iso8859-9.c
@@ -171,7 +171,42 @@ static unsigned char *page_uni2charset[256] = {
page00, page01, NULL, NULL, NULL, NULL, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0x69, 0xfe, 0xdf, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -185,28 +220,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
- 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
- 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
- 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
- 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0x00, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
- 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, /* 0xf0-0xf7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0x49, 0xde, 0x00, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -222,6 +258,8 @@ static struct nls_table table = {
"iso8859-9",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/nls/nls_koi8-r.c b/fs/nls/nls_koi8-r.c
index c6ee51f99..3dc3effaa 100644
--- a/fs/nls/nls_koi8-r.c
+++ b/fs/nls/nls_koi8-r.c
@@ -283,7 +283,42 @@ static unsigned char *page_uni2charset[256] = {
NULL, NULL, page22, page23, NULL, page25, NULL, NULL,
};
-#if 0
+static unsigned char charset2lower[256] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+ 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+ 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+ 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+ 0xb0, 0xb1, 0xb2, 0xa3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xf0-0xf7 */
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xf8-0xff */
+};
+
static unsigned char charset2upper[256] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
@@ -297,28 +332,29 @@ static unsigned char charset2upper[256] = {
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
- 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
- 0x00, 0x00, 0x00, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+ 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+ 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+ 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
- 0xa0, 0xa1, 0xa2, 0x00, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+ 0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xd0-0xd7 */
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xd8-0xdf */
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
};
-#endif
+
static void inc_use_count(void)
{
@@ -334,6 +370,8 @@ static struct nls_table table = {
"koi8-r",
page_uni2charset,
charset2uni,
+ charset2lower,
+ charset2upper,
inc_use_count,
dec_use_count,
NULL
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index 4fe6df055..b087bd7f6 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -442,10 +442,8 @@ static struct inode_operations ntfs_inode_operations_nobmap = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -625,10 +623,8 @@ static struct inode_operations ntfs_inode_operations = {
ntfs_bmap, /* get_block */
block_read_full_page, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -674,10 +670,8 @@ static struct inode_operations ntfs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL, /* revalidate */
};
@@ -818,6 +812,7 @@ static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
struct statfs fs;
struct inode *mft;
ntfs_volume *vol;
+ ntfs_u64 size;
int error;
ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
@@ -826,16 +821,21 @@ static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
fs.f_type=NTFS_SUPER_MAGIC;
fs.f_bsize=vol->clustersize;
- error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &fs.f_blocks );
+ error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size );
if( error )
return -error;
+ fs.f_blocks = size; /* volumesize is in clusters */
fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
fs.f_bavail=fs.f_bfree;
/* Number of files is limited by free space only, so we lie here */
fs.f_ffree=0;
mft=iget(sb,FILE_MFT);
- fs.f_files=mft->i_size/vol->mft_recordsize;
+ if (!mft)
+ return -EIO;
+ /* So ... we lie... thus this following cast of loff_t value
+ is ok here.. */
+ fs.f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
iput(mft);
/* should be read from volume */
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 51f14e72b..d7dcb127f 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -253,10 +253,9 @@ int ntfs_release_volume(ntfs_volume *vol)
* Writes the volume size into vol_size. Returns 0 if successful
* or error.
*/
-int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size )
+int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size )
{
ntfs_io io;
- ntfs_u64 size;
char *cluster0;
if( !vol_size )
@@ -272,11 +271,8 @@ int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size )
io.do_read=1;
io.size=vol->clustersize;
ntfs_getput_clusters(vol,0,0,&io);
- size=NTFS_GETU64(cluster0+0x28);
+ *vol_size = NTFS_GETU64(cluster0+0x28);
ntfs_free(cluster0);
- /* FIXME: more than 2**32 cluster */
- /* FIXME: gcc will emit udivdi3 if we don't truncate it */
- *vol_size = ((unsigned long)size)/vol->clusterfactor;
return 0;
}
diff --git a/fs/ntfs/super.h b/fs/ntfs/super.h
index b74772143..3afbf7e47 100644
--- a/fs/ntfs/super.h
+++ b/fs/ntfs/super.h
@@ -10,7 +10,7 @@
#define ALLOC_REQUIRE_SIZE 2
int ntfs_get_free_cluster_count(ntfs_inode *bitmap);
-int ntfs_get_volumesize(ntfs_volume *vol, long *vol_size );
+int ntfs_get_volumesize(ntfs_volume *vol, ntfs_u64 *vol_size );
int ntfs_init_volume(ntfs_volume *vol,char *boot);
int ntfs_load_special_files(ntfs_volume *vol);
int ntfs_release_volume(ntfs_volume *vol);
diff --git a/fs/open.c b/fs/open.c
index 8c8d5698d..c5f571ce1 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -55,14 +55,14 @@ out:
return error;
}
-int do_truncate(struct dentry *dentry, unsigned long length)
+int do_truncate(struct dentry *dentry, loff_t length)
{
struct inode *inode = dentry->d_inode;
int error;
struct iattr newattrs;
- /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
- if ((off_t) length < 0)
+ /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
+ if (length < 0)
return -EINVAL;
down(&inode->i_sem);
@@ -79,13 +79,18 @@ int do_truncate(struct dentry *dentry, unsigned long length)
return error;
}
-asmlinkage long sys_truncate(const char * path, unsigned long length)
+static inline long do_sys_truncate(const char * path, loff_t length)
{
struct dentry * dentry;
struct inode * inode;
int error;
lock_kernel();
+
+ error = -EINVAL;
+ if (length < 0) /* sorry, but loff_t says... */
+ goto out;
+
dentry = namei(path);
error = PTR_ERR(dentry);
@@ -128,13 +133,21 @@ out:
return error;
}
-asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
+asmlinkage long sys_truncate(const char * path, unsigned long length)
+{
+ return do_sys_truncate(path, length);
+}
+
+static inline long do_sys_ftruncate(unsigned int fd, loff_t length)
{
struct inode * inode;
struct dentry *dentry;
struct file * file;
int error;
+ error = -EINVAL;
+ if (length < 0)
+ goto out;
error = -EBADF;
file = fget(fd);
if (!file)
@@ -163,6 +176,24 @@ out:
return error;
}
+asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
+{
+ return do_sys_ftruncate(fd, length);
+}
+
+/* LFS versions of truncate are only needed on 32 bit machines */
+#if BITS_PER_LONG == 32
+asmlinkage long sys_truncate64(const char * path, loff_t length)
+{
+ return do_sys_truncate(path, length);
+}
+
+asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
+{
+ return do_sys_ftruncate(fd, length);
+}
+#endif
+
#if !(defined(__alpha__) || defined(__ia64__))
/*
diff --git a/fs/partitions/Config.in b/fs/partitions/Config.in
index c07773786..de35b3d57 100644
--- a/fs/partitions/Config.in
+++ b/fs/partitions/Config.in
@@ -18,7 +18,8 @@ else
define_bool CONFIG_MSDOS_PARTITION y
fi
fi
-if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
+if [ "$CONFIG_PARTITION_ADVANCED" = "y" -a \
+ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
bool ' BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
bool ' Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
bool ' Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
diff --git a/fs/pipe.c b/fs/pipe.c
index 7cdd2b394..68922b9b8 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -51,6 +51,7 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
/* Seeks are not allowed on pipes. */
ret = -ESPIPE;
+ read = 0;
if (ppos != &filp->f_pos)
goto out_nolock;
@@ -65,6 +66,7 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
goto out_nolock;
if (PIPE_EMPTY(*inode)) {
+do_more_read:
ret = 0;
if (!PIPE_WRITERS(*inode))
goto out;
@@ -74,7 +76,9 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
goto out;
for (;;) {
+ PIPE_WAITING_READERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_READERS(*inode)--;
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
@@ -90,7 +94,6 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
/* Read what data is available. */
ret = -EFAULT;
- read = 0;
while (count > 0 && (size = PIPE_LEN(*inode))) {
char *pipebuf = PIPE_BASE(*inode) + PIPE_START(*inode);
ssize_t chars = PIPE_MAX_RCHUNK(*inode);
@@ -115,16 +118,26 @@ pipe_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
if (!PIPE_LEN(*inode))
PIPE_START(*inode) = 0;
- /* Signal writers there is more room. */
+ if (count && PIPE_WAITING_WRITERS(*inode) && !(filp->f_flags & O_NONBLOCK)) {
+ /*
+ * We know that we are going to sleep: signal
+ * writers synchronously that there is more
+ * room.
+ */
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ if (!PIPE_EMPTY(*inode))
+ BUG();
+ goto do_more_read;
+ }
+ /* Signal writers asynchronously that there is more room. */
wake_up_interruptible(PIPE_WAIT(*inode));
- if (read)
- UPDATE_ATIME(inode);
ret = read;
-
out:
up(PIPE_SEM(*inode));
out_nolock:
+ if (read)
+ ret = read;
return ret;
}
@@ -136,6 +149,7 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
/* Seeks are not allowed on pipes. */
ret = -ESPIPE;
+ written = 0;
if (ppos != &filp->f_pos)
goto out_nolock;
@@ -148,13 +162,13 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
if (down_interruptible(PIPE_SEM(*inode)))
goto out_nolock;
+do_more_write:
/* No readers yields SIGPIPE. */
if (!PIPE_READERS(*inode))
goto sigpipe;
/* If count <= PIPE_BUF, we have to make it atomic. */
free = (count <= PIPE_BUF ? count : 1);
- written = 0;
/* Wait, or check for, available space. */
if (filp->f_flags & O_NONBLOCK) {
@@ -163,7 +177,9 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
goto out;
} else {
while (PIPE_FREE(*inode) < free) {
+ PIPE_WAITING_WRITERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_WRITERS(*inode)--;
ret = -ERESTARTSYS;
if (signal_pending(current))
goto out_nolock;
@@ -204,9 +220,15 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
break;
do {
- /* This should be a synchronous wake-up: don't do idle reschedules! */
- wake_up_interruptible(PIPE_WAIT(*inode));
+ /*
+ * Synchronous wake-up: it knows that this process
+ * is going to give up this CPU, so it doesnt have
+ * to do idle reschedules.
+ */
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ PIPE_WAITING_WRITERS(*inode)++;
pipe_wait(inode);
+ PIPE_WAITING_WRITERS(*inode)--;
if (signal_pending(current))
goto out_nolock;
if (down_interruptible(PIPE_SEM(*inode)))
@@ -217,19 +239,27 @@ pipe_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
ret = -EFAULT;
}
- /* Signal readers there is more data. */
+ if (count && PIPE_WAITING_READERS(*inode) &&
+ !(filp->f_flags & O_NONBLOCK)) {
+ wake_up_interruptible_sync(PIPE_WAIT(*inode));
+ goto do_more_write;
+ }
+ /* Signal readers asynchronously that there is more data. */
wake_up_interruptible(PIPE_WAIT(*inode));
- ret = (written ? written : -EAGAIN);
inode->i_ctime = inode->i_mtime = CURRENT_TIME;
mark_inode_dirty(inode);
out:
up(PIPE_SEM(*inode));
out_nolock:
+ if (written)
+ ret = written;
return ret;
sigpipe:
+ if (written)
+ goto out;
up(PIPE_SEM(*inode));
send_sig(SIGPIPE, current, 0);
return -EPIPE;
@@ -552,6 +582,7 @@ static struct inode * get_pipe_inode(void)
PIPE_BASE(*inode) = (char *) page;
PIPE_START(*inode) = PIPE_LEN(*inode) = 0;
PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 1;
+ PIPE_WAITING_READERS(*inode) = PIPE_WAITING_WRITERS(*inode) = 0;
/*
* Mark the inode dirty from the very beginning,
@@ -577,25 +608,6 @@ fail_inode:
struct inode_operations pipe_inode_operations = {
&rdwr_pipe_fops,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
int do_pipe(int *fd)
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 8ff6cd522..e8bb4774f 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -18,9 +18,11 @@ M_OBJS :=
ifeq ($(CONFIG_SUN_OPENPROMFS),y)
O_OBJS += openpromfs.o
+OX_OBJS := openprom-dev.o
else
ifeq ($(CONFIG_SUN_OPENPROMFS),m)
M_OBJS += openpromfs.o
+ OX_OBJS := openprom-dev.o
endif
endif
diff --git a/fs/proc/array.c b/fs/proc/array.c
index eebb1f470..4ae097ca2 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -62,7 +62,6 @@
#include <linux/mman.h>
#include <linux/proc_fs.h>
#include <linux/ioport.h>
-#include <linux/config.h>
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/swap.h>
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 866bb50d4..eac10cbd4 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -104,9 +104,12 @@ static int proc_pid_environ(struct task_struct *task, char * buffer)
{
struct mm_struct *mm = task->mm;
int res = 0;
- if (mm)
- res = access_process_vm(task, mm->env_start, buffer,
- mm->env_end - mm->env_start, 0);
+ if (mm) {
+ int len = mm->env_end - mm->env_start;
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ res = access_process_vm(task, mm->env_start, buffer, len, 0);
+ }
return res;
}
@@ -116,9 +119,12 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
struct mm_struct *mm = task->mm;
int res = 0;
- if (mm)
- res = access_process_vm(task, mm->arg_start, buffer,
- mm->arg_end - mm->arg_start, 0);
+ if (mm) {
+ int len = mm->arg_end - mm->arg_start;
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ res = access_process_vm(task, mm->arg_start, buffer, len, 0);
+ }
return res;
}
@@ -363,10 +369,8 @@ static struct inode_operations proc_mem_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
proc_permission, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -788,7 +792,6 @@ static struct inode_operations proc_fd_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
proc_permission, /* permission */
};
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 5ef59004c..5f43c691e 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -16,8 +16,6 @@
#include <linux/stat.h>
#include <asm/bitops.h>
-extern struct inode_operations proc_dyna_dir_inode_operations;
-
static ssize_t proc_file_read(struct file * file, char * buf,
size_t nbytes, loff_t *ppos);
static ssize_t proc_file_write(struct file * file, const char * buffer,
@@ -37,37 +35,10 @@ static struct file_operations proc_file_operations = {
proc_file_lseek, /* lseek */
proc_file_read, /* read */
proc_file_write, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- NULL, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
};
-struct inode_operations proc_file_inode_operations = {
+static struct inode_operations proc_file_inode_operations = {
&proc_file_operations, /* default proc file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
#ifndef MIN
@@ -101,12 +72,8 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
/*
* Handle backwards compatibility with the old net
* routines.
- *
- * XXX What gives with the file->f_flags & O_ACCMODE
- * test? Seems stupid to me....
*/
- n = dp->get_info(page, &start, *ppos, count,
- (file->f_flags & O_ACCMODE) == O_RDWR);
+ n = dp->get_info(page, &start, *ppos, count);
if (n < count)
eof = 1;
} else if (dp->read_proc) {
@@ -114,7 +81,7 @@ proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
count, &eof, dp->data);
} else
break;
-
+
if (!start) {
/*
* For proc files that are less than 4k
@@ -221,6 +188,321 @@ static int xlate_proc_name(const char *name,
return 0;
}
+static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
+
+static int make_inode_number(void)
+{
+ int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
+ if (i<0 || i>=PROC_NDYNAMIC)
+ return -1;
+ set_bit(i, (void *) proc_alloc_map);
+ return PROC_DYNAMIC_FIRST + i;
+}
+
+static int proc_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+ char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_readlink(dentry, buffer, buflen, s);
+}
+
+static struct dentry *proc_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
+{
+ char *s=((struct proc_dir_entry *)dentry->d_inode->u.generic_ip)->data;
+ return vfs_follow_link(dentry, base, flags, s);
+}
+
+static struct inode_operations proc_link_inode_operations = {
+ readlink: proc_readlink,
+ follow_link: proc_follow_link
+};
+
+/*
+ * As some entries in /proc are volatile, we want to
+ * get rid of unused dentries. This could be made
+ * smarter: we could keep a "volatile" flag in the
+ * inode to indicate which ones to keep.
+ */
+static void
+proc_delete_dentry(struct dentry * dentry)
+{
+ d_drop(dentry);
+}
+
+static struct dentry_operations proc_dentry_operations =
+{
+ NULL, /* revalidate */
+ NULL, /* d_hash */
+ NULL, /* d_compare */
+ proc_delete_dentry /* d_delete(struct dentry *) */
+};
+
+/*
+ * Don't create negative dentries here, return -ENOENT by hand
+ * instead.
+ */
+struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
+{
+ struct inode *inode;
+ struct proc_dir_entry * de;
+ int error;
+
+ error = -ENOENT;
+ inode = NULL;
+ de = (struct proc_dir_entry *) dir->u.generic_ip;
+ if (de) {
+ for (de = de->subdir; de ; de = de->next) {
+ if (!de || !de->low_ino)
+ continue;
+ if (de->namelen != dentry->d_name.len)
+ continue;
+ if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
+ int ino = de->low_ino;
+ error = -EINVAL;
+ inode = proc_get_inode(dir->i_sb, ino, de);
+ break;
+ }
+ }
+ }
+
+ if (inode) {
+ dentry->d_op = &proc_dentry_operations;
+ d_add(dentry, inode);
+ return NULL;
+ }
+ return ERR_PTR(error);
+}
+
+/*
+ * This returns non-zero if at EOF, so that the /proc
+ * root directory can use this and check if it should
+ * continue with the <pid> entries..
+ *
+ * Note that the VFS-layer doesn't care about the return
+ * value of the readdir() call, as long as it's non-negative
+ * for success..
+ */
+int proc_readdir(struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ struct proc_dir_entry * de;
+ unsigned int ino;
+ int i;
+ struct inode *inode = filp->f_dentry->d_inode;
+
+ ino = inode->i_ino;
+ de = (struct proc_dir_entry *) inode->u.generic_ip;
+ if (!de)
+ return -EINVAL;
+ i = filp->f_pos;
+ switch (i) {
+ case 0:
+ if (filldir(dirent, ".", 1, i, ino) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ if (filldir(dirent, "..", 2, i,
+ filp->f_dentry->d_parent->d_inode->i_ino
+ ) < 0)
+ return 0;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ default:
+ de = de->subdir;
+ i -= 2;
+ for (;;) {
+ if (!de)
+ return 1;
+ if (!i)
+ break;
+ de = de->next;
+ i--;
+ }
+
+ do {
+ if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
+ return 0;
+ filp->f_pos++;
+ de = de->next;
+ } while (de);
+ }
+ return 1;
+}
+
+/*
+ * These are the generic /proc directory operations. They
+ * use the in-memory "struct proc_dir_entry" tree to parse
+ * the /proc directory.
+ */
+static struct file_operations proc_dir_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_readdir, /* readdir */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_dir_inode_operations = {
+ &proc_dir_operations, /* default net directory file-ops */
+ NULL, /* create */
+ proc_lookup, /* lookup */
+};
+
+int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+{
+ int i;
+
+ i = make_inode_number();
+ if (i < 0)
+ return -EAGAIN;
+ dp->low_ino = i;
+ dp->next = dir->subdir;
+ dp->parent = dir;
+ dir->subdir = dp;
+ if (S_ISDIR(dp->mode)) {
+ if (dp->ops == NULL)
+ dp->ops = &proc_dir_inode_operations;
+ dir->nlink++;
+ } else if (S_ISLNK(dp->mode)) {
+ if (dp->ops == NULL)
+ dp->ops = &proc_link_inode_operations;
+ } else if (S_ISREG(dp->mode)) {
+ if (dp->ops == NULL)
+ dp->ops = &proc_file_inode_operations;
+ }
+ return 0;
+}
+
+/*
+ * Kill an inode that got unregistered..
+ */
+static void proc_kill_inodes(struct proc_dir_entry *de)
+{
+ struct list_head *p;
+ struct super_block *sb;
+
+ /*
+ * Actually it's a partial revoke(). We have to go through all
+ * copies of procfs. proc_super_blocks is protected by the big
+ * lock for the time being.
+ */
+ for (sb = proc_super_blocks;
+ sb;
+ sb = (struct super_block*)sb->u.generic_sbp) {
+ file_list_lock();
+ for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
+ struct file * filp = list_entry(p, struct file, f_list);
+ struct dentry * dentry;
+ struct inode * inode;
+
+ dentry = filp->f_dentry;
+ if (!dentry)
+ continue;
+ if (dentry->d_op != &proc_dentry_operations)
+ continue;
+ inode = dentry->d_inode;
+ if (!inode)
+ continue;
+ if (inode->u.generic_ip != de)
+ continue;
+ filp->f_op = NULL;
+ }
+ file_list_unlock();
+ }
+}
+
+struct proc_dir_entry *proc_symlink(const char *name,
+ struct proc_dir_entry *parent, char *dest)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->nlink = 1;
+ ent->mode = S_IFLNK|S_IRUGO|S_IWUGO|S_IXUGO;
+ ent->data = kmalloc((ent->size=strlen(dest))+1, GFP_KERNEL);
+ if (!ent->data) {
+ kfree(ent);
+ goto out;
+ }
+ strcpy((char*)ent->data,dest);
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
+struct proc_dir_entry *proc_mknod(const char *name, mode_t mode,
+ struct proc_dir_entry *parent, kdev_t rdev)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->nlink = 1;
+ ent->mode = mode;
+ ent->rdev = rdev;
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
+struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent)
+{
+ struct proc_dir_entry *ent = NULL;
+ const char *fn = name;
+ int len;
+
+ if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
+ goto out;
+ len = strlen(fn);
+
+ ent = kmalloc(sizeof(struct proc_dir_entry) + len + 1, GFP_KERNEL);
+ if (!ent)
+ goto out;
+ memset(ent, 0, sizeof(struct proc_dir_entry));
+ memcpy(((char *) ent) + sizeof(*ent), fn, len + 1);
+ ent->name = ((char *) ent) + sizeof(*ent);
+ ent->namelen = len;
+ ent->ops = &proc_dir_inode_operations;
+ ent->nlink = 2;
+ ent->mode = S_IFDIR | S_IRUGO | S_IXUGO;
+
+ proc_register(parent, ent);
+
+out:
+ return ent;
+}
+
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
struct proc_dir_entry *parent)
{
@@ -243,7 +525,7 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
if (S_ISDIR(mode)) {
if ((mode & S_IALLUGO) == 0)
mode |= S_IRUGO | S_IXUGO;
- ent->ops = &proc_dyna_dir_inode_operations;
+ ent->ops = &proc_dir_inode_operations;
ent->nlink = 2;
} else {
if ((mode & S_IFMT) == 0)
@@ -260,14 +542,16 @@ out:
return ent;
}
-extern void free_proc_entry(struct proc_dir_entry *);
void free_proc_entry(struct proc_dir_entry *de)
{
int ino = de->low_ino;
- if (ino >= PROC_DYNAMIC_FIRST &&
- ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
- kfree(de);
+ if (ino < PROC_DYNAMIC_FIRST &&
+ ino >= PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
+ return;
+ if (S_ISLNK(de->mode) && de->data)
+ kfree(de->data);
+ kfree(de);
}
/*
@@ -276,6 +560,7 @@ void free_proc_entry(struct proc_dir_entry *de)
*/
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
{
+ struct proc_dir_entry **p;
struct proc_dir_entry *de;
const char *fn = name;
int len;
@@ -283,14 +568,17 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
if (!parent && xlate_proc_name(name, &parent, &fn) != 0)
goto out;
len = strlen(fn);
-
- for (de = parent->subdir; de ; de = de->next) {
- if (proc_match(len, fn, de))
- break;
- }
-
- if (de) {
- proc_unregister(parent, de->low_ino);
+ for (p = &parent->subdir; *p; p=&(*p)->next ) {
+ if (!proc_match(len, fn, *p))
+ continue;
+ de = *p;
+ *p = de->next;
+ de->next = NULL;
+ if (S_ISDIR(de->mode))
+ parent->nlink--;
+ clear_bit(de->low_ino-PROC_DYNAMIC_FIRST,
+ (void *) proc_alloc_map);
+ proc_kill_inodes(de);
de->nlink = 0;
de->deleted = 1;
if (!de->count)
@@ -299,6 +587,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
printk("remove_proc_entry: %s/%s busy, count=%d\n",
parent->name, de->name, de->count);
}
+ break;
}
out:
return;
diff --git a/fs/proc/inode-alloc.txt b/fs/proc/inode-alloc.txt
index 4af79966c..fbcfa4e40 100644
--- a/fs/proc/inode-alloc.txt
+++ b/fs/proc/inode-alloc.txt
@@ -5,7 +5,6 @@ Current inode allocations in the proc-fs (hex-numbers):
001 root-ino
00001000-00001fff dynamic entries
- 00002000-00002fff openprom entries
0001xxxx-7fffxxxx pid-dir entries for pid 1-7fff
80000000-ffffffff unused
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 8842cc253..607a7d7e9 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -13,7 +13,7 @@
#include <linux/file.h>
#include <linux/locks.h>
#include <linux/limits.h>
-#include <linux/config.h>
+#define __NO_VERSION__
#include <linux/module.h>
#include <asm/system.h>
@@ -51,10 +51,6 @@ void de_put(struct proc_dir_entry *de)
static void proc_put_inode(struct inode *inode)
{
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
- if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
- (*proc_openprom_use)(inode, 0);
-#endif
/*
* Kill off unused inodes ... VFS will unhash and
* delete the inode if we set i_nlink to zero.
@@ -74,9 +70,6 @@ static void proc_delete_inode(struct inode *inode)
proc_pid_delete_inode(inode);
return;
}
- if (PROC_INODE_OPENPROM(inode))
- return;
-
if (de) {
if (de->owner)
__MOD_DEC_USE_COUNT(de->owner);
@@ -97,6 +90,30 @@ static void proc_put_super(struct super_block *sb)
*p = (struct super_block *)(*p)->u.generic_sbp;
}
+static void proc_write_inode(struct inode * inode)
+{
+}
+
+static void proc_read_inode(struct inode * inode)
+{
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+}
+
+static int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = PROC_SUPER_MAGIC;
+ tmp.f_bsize = PAGE_SIZE/sizeof(long);
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
static struct super_operations proc_sops = {
proc_read_inode,
proc_write_inode,
@@ -158,11 +175,6 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
if (!inode)
goto out_fail;
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
- if (PROC_INODE_OPENPROM(inode) && proc_openprom_use)
- (*proc_openprom_use)(inode, 1);
-#endif
-
inode->u.generic_ip = (void *) de;
if (de) {
if (de->mode) {
@@ -172,26 +184,16 @@ printk("proc_iget: using deleted entry %s, count=%d\n", de->name, de->count);
}
if (de->size)
inode->i_size = de->size;
- if (de->ops)
- inode->i_op = de->ops;
if (de->nlink)
inode->i_nlink = de->nlink;
if (de->owner)
__MOD_INC_USE_COUNT(de->owner);
+ if (S_ISBLK(de->mode)||S_ISCHR(de->mode)||S_ISFIFO(de->mode))
+ init_special_inode(inode,de->mode,kdev_t_to_nr(de->rdev));
+ else if (de->ops)
+ inode->i_op = de->ops;
}
- /*
- * Fixup the root inode's nlink value
- */
- if (inode->i_ino == PROC_ROOT_INO) {
- struct task_struct *p;
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if (p->pid)
- inode->i_nlink++;
- }
- read_unlock(&tasklist_lock);
- }
out:
return inode;
@@ -204,6 +206,7 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
int silent)
{
struct inode * root_inode;
+ struct task_struct *p;
lock_super(s);
s->s_blocksize = 1024;
@@ -213,6 +216,12 @@ struct super_block *proc_read_super(struct super_block *s,void *data,
root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
if (!root_inode)
goto out_no_root;
+ /*
+ * Fixup the root inode's nlink value
+ */
+ read_lock(&tasklist_lock);
+ for_each_task(p) if (p->pid) root_inode->i_nlink++;
+ read_unlock(&tasklist_lock);
s->s_root = d_alloc_root(root_inode);
if (!s->s_root)
goto out_no_root;
@@ -229,27 +238,3 @@ out_no_root:
unlock_super(s);
return NULL;
}
-
-int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
-{
- struct statfs tmp;
-
- tmp.f_type = PROC_SUPER_MAGIC;
- tmp.f_bsize = PAGE_SIZE/sizeof(long);
- tmp.f_blocks = 0;
- tmp.f_bfree = 0;
- tmp.f_bavail = 0;
- tmp.f_files = 0;
- tmp.f_ffree = 0;
- tmp.f_namelen = NAME_MAX;
- return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
-}
-
-void proc_read_inode(struct inode * inode)
-{
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-}
-
-void proc_write_inode(struct inode * inode)
-{
-}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index ec2a92db3..28635ff14 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -3,9 +3,9 @@
*
* Modelled on fs/exec.c:aout_core_dump()
* Jeremy Fitzhardinge <jeremy@sw.oz.au>
- * Implemented by David Howells <David.Howells@nexor.co.uk>
+ * ELF version written by David Howells <David.Howells@nexor.co.uk>
* Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com>
- * Support to dump vmalloc'd data structures (ELF only), Tigran Aivazian <tigran@sco.com>
+ * Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@sco.com>
*/
#include <linux/config.h>
@@ -16,7 +16,6 @@
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/vmalloc.h>
-#include <linux/proc_fs.h>
#include <asm/uaccess.h>
@@ -43,8 +42,7 @@ struct inode_operations proc_kcore_inode_operations = {
};
#ifdef CONFIG_KCORE_AOUT
-static ssize_t read_kcore(struct file * file, char * buf,
- size_t count, loff_t *ppos)
+static ssize_t read_kcore(struct file *file, char *buf, size_t count, loff_t *ppos)
{
unsigned long long p = *ppos, memsize;
ssize_t read;
@@ -79,7 +77,8 @@ static ssize_t read_kcore(struct file * file, char * buf,
if (p + count1 > sizeof(struct user))
count1 = sizeof(struct user)-p;
pnt = (char *) &dump + p;
- copy_to_user(buf,(void *) pnt, count1);
+ if (copy_to_user(buf,(void *) pnt, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
@@ -90,14 +89,16 @@ static ssize_t read_kcore(struct file * file, char * buf,
count1 = PAGE_SIZE + FIRST_MAPPED - p;
if (count1 > count)
count1 = count;
- clear_user(buf, count1);
+ if (clear_user(buf, count1))
+ return -EFAULT;
buf += count1;
p += count1;
count -= count1;
read += count1;
}
if (count > 0) {
- copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count);
+ if (copy_to_user(buf, (void *) (PAGE_OFFSET+p-PAGE_SIZE), count))
+ return -EFAULT;
read += count;
}
*ppos += read;
@@ -130,6 +131,8 @@ static size_t get_kcore_size(int *num_vma, int *elf_buflen)
}
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
try = (size_t)m->addr + m->size;
if (try > size)
size = try;
@@ -189,7 +192,7 @@ static char *storenote(struct memelfnote *men, char *bufp)
* store an ELF coredump header in the supplied buffer
* num_vma is the number of elements in vmlist
*/
-static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
+static void elf_kcore_store_hdr(char *bufp, int num_vma, int dataoff)
{
struct elf_prstatus prstatus; /* NT_PRSTATUS */
struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */
@@ -235,28 +238,33 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
nhdr->p_flags = 0;
nhdr->p_align = 0;
- /* setup ELF PT_LOAD program header */
+ /* setup ELF PT_LOAD program header for the
+ * virtual range 0xc0000000 -> high_memory */
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = elf_buflen;
+ phdr->p_offset = dataoff;
phdr->p_vaddr = PAGE_OFFSET;
phdr->p_paddr = __pa(PAGE_OFFSET);
phdr->p_filesz = phdr->p_memsz = ((unsigned long)high_memory - PAGE_OFFSET);
phdr->p_align = PAGE_SIZE;
+ /* setup ELF PT_LOAD program header for every vmalloc'd area */
for (m=vmlist; m; m=m->next) {
+ if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
+ continue;
+
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
- phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + elf_buflen;
+ phdr->p_offset = (size_t)m->addr - PAGE_OFFSET + dataoff;
phdr->p_vaddr = (size_t)m->addr;
- phdr->p_paddr = __pa(m);
+ phdr->p_paddr = __pa(m->addr);
phdr->p_filesz = phdr->p_memsz = m->size;
phdr->p_align = PAGE_SIZE;
}
@@ -310,13 +318,12 @@ static void elf_kcore_store_hdr(char *bufp, int num_vma, int elf_buflen)
/*
* read from the ELF header and then kernel memory
*/
-static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
- loff_t *fpos)
+static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos)
{
ssize_t acc = 0;
size_t size, tsz;
- char * elf_buffer;
- int elf_buflen = 0, num_vma = 0;
+ size_t elf_buflen;
+ int num_vma;
/* XXX we need to somehow lock vmlist between here
* and after elf_kcore_store_hdr() returns.
@@ -332,16 +339,21 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* construct an ELF core header if we'll need some of it */
if (*fpos < elf_buflen) {
+ char * elf_buf;
+
tsz = elf_buflen - *fpos;
if (buflen < tsz)
tsz = buflen;
- elf_buffer = kmalloc(elf_buflen, GFP_KERNEL);
- if (!elf_buffer)
+ elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
+ if (!elf_buf)
return -ENOMEM;
- memset(elf_buffer, 0, elf_buflen);
- elf_kcore_store_hdr(elf_buffer, num_vma, elf_buflen);
- copy_to_user(buffer, elf_buffer, tsz);
- kfree(elf_buffer);
+ memset(elf_buf, 0, elf_buflen);
+ elf_kcore_store_hdr(elf_buf, num_vma, elf_buflen);
+ if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
+ kfree(elf_buf);
+ return -EFAULT;
+ }
+ kfree(elf_buf);
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -349,7 +361,7 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
/* leave now if filled buffer already */
if (buflen == 0)
- return tsz;
+ return acc;
}
/* where page 0 not mapped, write zeros into buffer */
@@ -361,7 +373,8 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
tsz = buflen;
/* write zeros to buffer */
- clear_user(buffer, tsz);
+ if (clear_user(buffer, tsz))
+ return -EFAULT;
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
@@ -372,17 +385,12 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen,
return tsz;
}
#endif
-
/* fill the remainder of the buffer from kernel VM space */
-#if defined (__i386__) || defined (__mc68000__)
- copy_to_user(buffer, __va(*fpos - PAGE_SIZE), buflen);
-#else
- copy_to_user(buffer, __va(*fpos), buflen);
-#endif
+ if (copy_to_user(buffer, __va(*fpos - elf_buflen), buflen))
+ return -EFAULT;
+
acc += buflen;
*fpos += buflen;
-
return acc;
-
}
#endif /* CONFIG_KCORE_AOUT */
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index bfe6c8c2e..b9344ba55 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -61,23 +61,4 @@ static struct file_operations proc_kmsg_operations = {
struct inode_operations proc_kmsg_inode_operations = {
&proc_kmsg_operations, /* default base directory file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
diff --git a/fs/proc/omirr.c b/fs/proc/omirr.c
index f738827a7..f205dd753 100644
--- a/fs/proc/omirr.c
+++ b/fs/proc/omirr.c
@@ -278,23 +278,4 @@ static struct file_operations omirr_operations = {
struct inode_operations proc_omirr_inode_operations = {
&omirr_operations,
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
diff --git a/fs/proc/openprom-dev.c b/fs/proc/openprom-dev.c
new file mode 100644
index 000000000..79ef8d549
--- /dev/null
+++ b/fs/proc/openprom-dev.c
@@ -0,0 +1,46 @@
+/*
+ * linux/fs/proc/openprom-dev.c
+ *
+ * handling of devices attached to openpromfs.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+struct openpromfs_dev *openprom_devices = NULL;
+static ino_t openpromdev_ino = PROC_OPENPROMD_FIRST;
+
+int proc_openprom_regdev(struct openpromfs_dev *d)
+{
+ if (openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
+ return -1;
+ d->next = openprom_devices;
+ d->inode = openpromdev_ino++;
+ openprom_devices = d;
+ return 0;
+}
+
+int proc_openprom_unregdev(struct openpromfs_dev *d)
+{
+ if (d == openprom_devices) {
+ openprom_devices = d->next;
+ } else if (!openprom_devices)
+ return -1;
+ else {
+ struct openpromfs_dev *p;
+
+ for (p = openprom_devices; p->next != d && p->next; p = p->next);
+ if (!p->next) return -1;
+ p->next = d->next;
+ }
+ return 0;
+}
+
+#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
+EXPORT_SYMBOL(openprom_devices);
+#endif
diff --git a/fs/proc/openpromfs.c b/fs/proc/openpromfs.c
index c9553ea24..55f290664 100644
--- a/fs/proc/openpromfs.c
+++ b/fs/proc/openpromfs.c
@@ -50,8 +50,7 @@ static u16 options = 0xffff;
static u16 aliases = 0xffff;
static int aliases_nodes = 0;
static char *alias_names [ALIASES_NNODES];
-static struct inode_operations *proc_openprom_iops = 0;
-static struct openpromfs_dev **devices;
+extern struct openpromfs_dev *openprom_devices;
#define NODE(ino) nodes[ino - PROC_OPENPROM_FIRST]
#define NODE2INO(node) (node + PROC_OPENPROM_FIRST)
@@ -566,25 +565,6 @@ static struct file_operations openpromfs_prop_ops = {
static struct inode_operations openpromfs_prop_inode_ops = {
&openpromfs_prop_ops, /* default property file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
static struct file_operations openpromfs_nodenum_ops = {
@@ -603,25 +583,6 @@ static struct file_operations openpromfs_nodenum_ops = {
static struct inode_operations openpromfs_nodenum_inode_ops = {
&openpromfs_nodenum_ops,/* default .node file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- NULL, /* readlink */
- NULL, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
};
static struct file_operations openprom_alias_operations = {
@@ -654,13 +615,13 @@ static struct inode_operations openprom_alias_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
+extern struct inode_operations openprom_inode_operations;
+
static int lookup_children(u16 n, const char * name, int len)
{
int ret;
@@ -772,7 +733,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
}
}
if (!ino) {
- for (d = *devices; d; d = d->next)
+ for (d = openprom_devices; d; d = d->next)
if ((d->node == n) && (strlen (d->name) == len)
&& !strncmp (d->name, name, len)) {
ino = d->inode;
@@ -787,7 +748,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
else
return ERR_PTR(-ENOENT);
}
- inode = proc_get_inode (dir->i_sb, ino, 0);
+ inode = iget (dir->i_sb, ino, 0);
if (!inode)
return ERR_PTR(-EINVAL);
switch (type) {
@@ -797,7 +758,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
inode->i_mode |= S_IWUSR;
inode->i_op = &openprom_alias_inode_operations;
} else
- inode->i_op = proc_openprom_iops;
+ inode->i_op = &openprom_inode_operations;
inode->i_nlink = 2;
break;
case OPFSL_NODENUM:
@@ -825,11 +786,7 @@ static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentr
(((u16)(ino - NODEP2INO(NODE(dir->i_ino).first_prop) - 1)) << 16));
break;
case OPFSL_DEVICE:
- inode->i_mode = d->mode;
- inode->i_op = &chrdev_inode_operations;
- inode->i_nlink = 1;
- inode->i_rdev = d->rdev;
- break;
+ init_special_inode(d->mode, kdev_to_nr(d->rdev));
}
inode->i_gid = 0;
@@ -914,7 +871,7 @@ static int openpromfs_readdir(struct file * filp, void * dirent, filldir_t filld
}
}
}
- for (d = *devices; d; d = d->next) {
+ for (d = openprom_devices; d; d = d->next) {
if (d->node == n) {
if (i) i--;
else {
@@ -947,9 +904,8 @@ static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode
strncpy (p, dentry->d_name.name, dentry->d_name.len);
p [dentry->d_name.len] = 0;
alias_names [aliases_nodes++] = p;
- inode = proc_get_inode (dir->i_sb,
- NODEP2INO(NODE(dir->i_ino).first_prop)
- + aliases_nodes, 0);
+ inode = iget (dir->i_sb,
+ NODEP2INO(NODE(dir->i_ino).first_prop) + aliases_nodes);
if (!inode)
return -EINVAL;
inode->i_mode = S_IFREG | S_IRUGO | S_IWUSR;
@@ -1090,25 +1046,6 @@ void openpromfs_use (struct inode *inode, int inc)
{
static int root_fresh = 1;
static int dec_first = 1;
-#ifdef OPENPROM_DEBUGGING
- static int usec = 0;
-
- if (inc) {
- if (inode->i_count == 1)
- usec++;
- else if (root_fresh && inode->i_ino == PROC_OPENPROM_FIRST) {
- root_fresh = 0;
- usec++;
- }
- } else {
- if (inode->i_ino == PROC_OPENPROM_FIRST)
- root_fresh = 0;
- if (!dec_first)
- usec--;
- }
- printk ("openpromfs_use: %d %d %d %d\n",
- inode->i_ino, inc, usec, inode->i_count);
-#else
if (inc) {
if (inode->i_count == 1)
MOD_INC_USE_COUNT;
@@ -1122,7 +1059,6 @@ void openpromfs_use (struct inode *inode, int inc)
if (!dec_first)
MOD_DEC_USE_COUNT;
}
-#endif
dec_first = 0;
}
@@ -1130,39 +1066,131 @@ void openpromfs_use (struct inode *inode, int inc)
#define openpromfs_use 0
#endif
-#ifndef MODULE
-#define RET(x)
-void __init openpromfs_init (void)
-#else
+static struct file_operations openprom_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ openpromfs_readdir, /* readdir */
+};
-EXPORT_NO_SYMBOLS;
+static struct inode_operations openprom_inode_operations = {
+ &openprom_operations,/* default net directory file-ops */
+ NULL, /* create */
+ openpromfs_lookup, /* lookup */
+};
-#define RET(x) -x
-int init_module (void)
-#endif
+static void openprom_read_inode(struct inode * inode)
+{
+ inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+ if (inode->i_ino == PROC_OPENPROM) {
+ inode->i_op = &openprom_inode_operations;
+ }
+}
+
+static void openprom_put_super(struct super_block *sb)
+{
+ MOD_DEC_USE_COUNT;
+}
+
+static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+ struct statfs tmp;
+
+ tmp.f_type = PROC_SUPER_MAGIC; /* FIXME */
+ tmp.f_bsize = PAGE_SIZE/sizeof(long); /* ??? */
+ tmp.f_blocks = 0;
+ tmp.f_bfree = 0;
+ tmp.f_bavail = 0;
+ tmp.f_files = 0;
+ tmp.f_ffree = 0;
+ tmp.f_namelen = NAME_MAX;
+ return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations openprom_sops = {
+ openprom_read_inode,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ openprom_put_super,
+ NULL,
+ openprom_statfs,
+ NULL
+};
+
+struct super_block *openprom_read_super(struct super_block *s,void *data,
+ int silent)
+{
+ struct inode * root_inode;
+
+ MOD_INC_USE_COUNT;
+ lock_super(s);
+ s->s_blocksize = 1024;
+ s->s_blocksize_bits = 10;
+ s->s_magic = PROC_SUPER_MAGIC; /* FIXME */
+ s->s_op = &openprom_sops;
+ root_inode = iget(s, PROC_OPENPROM);
+ if (!root_inode)
+ goto out_no_root;
+ s->s_root = d_alloc_root(root_inode);
+ if (!s->s_root)
+ goto out_no_root;
+ unlock_super(s);
+ return s;
+
+out_no_root:
+ printk("proc_read_super: get root inode failed\n");
+ iput(root_inode);
+ s->s_dev = 0;
+ unlock_super(s);
+ return NULL;
+}
+
+static struct file_system_type openprom_fs_type = {
+ "openprom",
+ 0,
+ openprom_read_super,
+ NULL
+};
+
+static int init_openprom_fs(void)
{
nodes = (openpromfs_node *)__get_free_pages(GFP_KERNEL, 0);
if (!nodes) {
printk (KERN_WARNING "/proc/openprom: can't get free page\n");
- return RET(EIO);
+ return -EIO;
}
if (get_nodes (0xffff, prom_root_node) == 0xffff) {
printk (KERN_WARNING "/proc/openprom: couldn't setup tree\n");
- return RET(EIO);
+ return -EIO;
}
nodes[last_node].first_prop = first_prop;
- proc_openprom_iops = proc_openprom_register (openpromfs_readdir,
- openpromfs_lookup,
- openpromfs_use,
- &devices);
- return RET(0);
+ return register_filesystem(&openprom_fs_type);
+}
+
+#ifdef MODULE
+
+EXPORT_NO_SYMBOLS;
+
+int init_module (void)
+{
+ return init_openprom_fs();
+}
+
+#else
+
+void __init openpromfs_init (void)
+{
+ init_openprom_fs();
}
+#endif
#ifdef MODULE
void cleanup_module (void)
{
int i;
- proc_openprom_deregister ();
+ unregister_filesystem(&openprom_fs_type);
free_pages ((unsigned long)nodes, alloced);
for (i = 0; i < aliases_nodes; i++)
if (alias_names [i])
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index c06a802ce..1b4b7f23b 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -41,62 +41,6 @@ static int property_read_proc(char *page, char **start, off_t off,
* and "@10" to it.
*/
-static int devtree_readlink(struct dentry *, char *, int);
-static struct dentry *devtree_follow_link(struct dentry *, struct dentry *, unsigned int);
-
-struct inode_operations devtree_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- devtree_readlink, /* readlink */
- devtree_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-static struct dentry *devtree_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *link;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- link = (char *) de->data;
- return lookup_dentry(link, base, follow);
-}
-
-static int devtree_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *link;
- int linklen;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- link = (char *) de->data;
- linklen = strlen(link);
- if (linklen > buflen)
- linklen = buflen;
- if (copy_to_user(buffer, link, linklen))
- return -EFAULT;
- return linklen;
-}
-
/*
* Process a node, adding entries for its children and its properties.
*/
@@ -115,18 +59,11 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
* Unfortunately proc_register puts each new entry
* at the beginning of the list. So we rearrange them.
*/
- ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ ent = create_proc_read_entry(de, 0, pp->name,
+ property_read_proc, pp);
if (ent == 0)
break;
- memset(ent, 0, sizeof(struct proc_dir_entry));
- ent->name = pp->name;
- ent->namelen = strlen(pp->name);
- ent->mode = S_IFREG | S_IRUGO;
- ent->nlink = 1;
- ent->data = pp;
- ent->read_proc = property_read_proc;
ent->size = pp->length;
- proc_register(de, ent);
*lastp = ent;
lastp = &ent->next;
}
@@ -140,15 +77,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
l = strlen(p);
if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
l -= 2;
- ent = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ ent = proc_mkdir(de, p);
if (ent == 0)
break;
- memset(ent, 0, sizeof(struct proc_dir_entry));
- ent->name = p;
- ent->namelen = l;
- ent->mode = S_IFDIR | S_IRUGO | S_IXUGO;
- ent->nlink = 2;
- proc_register(de, ent);
*lastp = ent;
lastp = &ent->next;
add_node(child, ent);
@@ -168,18 +99,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
if (sib->name && strcmp(sib->name, child->name) == 0)
break;
if (sib == child && strncmp(p, child->name, l) != 0) {
- al = kmalloc(sizeof(struct proc_dir_entry),
- GFP_KERNEL);
+ al = proc_symlink(de, child->name, ent->name);
if (al == 0)
break;
- memset(al, 0, sizeof(struct proc_dir_entry));
- al->name = child->name;
- al->namelen = strlen(child->name);
- al->mode = S_IFLNK | S_IRUGO | S_IXUGO;
- al->nlink = 1;
- al->data = (void *) ent->name;
- al->ops = &devtree_symlink_inode_operations;
- proc_register(de, al);
*lastp = al;
lastp = &al->next;
}
@@ -187,16 +109,9 @@ static void add_node(struct device_node *np, struct proc_dir_entry *de)
/*
* Add another directory with the @address part as its name.
*/
- al = kmalloc(sizeof(struct proc_dir_entry), GFP_KERNEL);
+ al = proc_symlink(de, at, ent->name);
if (al == 0)
break;
- memset(al, 0, sizeof(struct proc_dir_entry));
- al->name = at;
- al->namelen = strlen(at);
- al->mode = S_IFLNK | S_IRUGO | S_IXUGO;
- al->nlink = 1;
- al->data = (void *) ent->name;
- al->ops = &devtree_symlink_inode_operations;
proc_register(de, al);
*lastp = al;
lastp = &al->next;
@@ -213,7 +128,7 @@ void proc_device_tree_init(void)
struct device_node *root;
if ( !have_of )
return;
- proc_device_tree = create_proc_entry("device-tree", S_IFDIR, 0);
+ proc_device_tree = proc_mkdir("device-tree", 0);
if (proc_device_tree == 0)
return;
root = find_path_device("/");
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 97f74a028..00b09e6a7 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -60,7 +60,6 @@ extern int get_filesystem_info(char *);
extern int get_exec_domain_list(char *);
extern int get_irq_list(char *);
extern int get_dma_list(char *);
-extern int get_rtc_status (char *);
extern int get_locks_status (char *, char **, off_t, int);
extern int get_swaparea_info (char *);
#ifdef CONFIG_SGI_DS1286
@@ -453,20 +452,6 @@ static int cmdline_read_proc(char *page, char **start, off_t off,
return len;
}
-#ifdef CONFIG_RTC
-static int rtc_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int len = get_rtc_status(page);
- if (len <= off+count) *eof = 1;
- *start = page + off;
- len -= off;
- if (len>count) len = count;
- if (len<0) len = 0;
- return len;
-}
-#endif
-
#ifdef CONFIG_SGI_DS1286
static int ds1286_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
@@ -665,9 +650,6 @@ void proc_misc_init(void)
{"dma", dma_read_proc},
{"ioports", ioports_read_proc},
{"cmdline", cmdline_read_proc},
-#ifdef CONFIG_RTC
- {"rtc", rtc_read_proc},
-#endif
#ifdef CONFIG_SGI_DS1286
{"rtc", ds1286_read_proc},
#endif
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c
index 4b4ca41b8..e241c938e 100644
--- a/fs/proc/proc_tty.c
+++ b/fs/proc/proc_tty.c
@@ -161,10 +161,9 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
if (!ent)
return;
- proc_unregister(proc_tty_driver, ent->low_ino);
+ remove_proc_entry(driver->driver_name, proc_tty_driver);
driver->proc_entry = 0;
- kfree(ent);
}
/*
@@ -172,18 +171,11 @@ void proc_tty_unregister_driver(struct tty_driver *driver)
*/
void __init proc_tty_init(void)
{
- struct proc_dir_entry *ent;
-
- ent = create_proc_entry("tty", S_IFDIR, 0);
- if (!ent)
+ if (!proc_mkdir("tty", 0))
return;
- proc_tty_ldisc = create_proc_entry("tty/ldisc", S_IFDIR, 0);
- proc_tty_driver = create_proc_entry("tty/driver", S_IFDIR, 0);
+ proc_tty_ldisc = proc_mkdir("tty/ldisc", 0);
+ proc_tty_driver = proc_mkdir("tty/driver", 0);
- ent = create_proc_entry("tty/ldiscs", 0, 0);
- ent->read_proc = tty_ldiscs_read_proc;
-
- ent = create_proc_entry("tty/drivers", 0, 0);
- ent->read_proc = tty_drivers_read_proc;
+ create_proc_read_entry("tty/ldiscs", 0, 0, tty_ldiscs_read_proc,NULL);
+ create_proc_read_entry("tty/drivers", 0, 0, tty_drivers_read_proc,NULL);
}
-
diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c
index fa2ee362e..7c986d615 100644
--- a/fs/proc/procfs_syms.c
+++ b/fs/proc/procfs_syms.c
@@ -8,22 +8,16 @@ extern struct proc_dir_entry *proc_sys_root;
#ifdef CONFIG_SYSCTL
EXPORT_SYMBOL(proc_sys_root);
#endif
-EXPORT_SYMBOL(proc_register);
-EXPORT_SYMBOL(proc_unregister);
+EXPORT_SYMBOL(proc_symlink);
+EXPORT_SYMBOL(proc_mknod);
+EXPORT_SYMBOL(proc_mkdir);
EXPORT_SYMBOL(create_proc_entry);
EXPORT_SYMBOL(remove_proc_entry);
EXPORT_SYMBOL(proc_root);
EXPORT_SYMBOL(proc_root_fs);
-EXPORT_SYMBOL(proc_get_inode);
-EXPORT_SYMBOL(proc_dir_inode_operations);
EXPORT_SYMBOL(proc_net);
EXPORT_SYMBOL(proc_bus);
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE)
-EXPORT_SYMBOL(proc_openprom_register);
-EXPORT_SYMBOL(proc_openprom_deregister);
-#endif
-
static struct file_system_type proc_fs_type = {
"proc",
0 /* FS_NO_DCACHE doesn't work correctly */,
diff --git a/fs/proc/root.c b/fs/proc/root.c
index b87b0fb4f..83a0d7619 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -15,383 +15,21 @@
#include <linux/config.h>
#include <linux/init.h>
#include <asm/bitops.h>
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-#ifdef CONFIG_ZORRO
-#include <linux/zorro.h>
-#endif
-
-static int proc_root_readdir(struct file *, void *, filldir_t);
-static struct dentry *proc_root_lookup(struct inode *,struct dentry *);
-static int proc_unlink(struct inode *, struct dentry *);
-
-static unsigned char proc_alloc_map[PROC_NDYNAMIC / 8] = {0};
-
-/*
- * These are the generic /proc directory operations. They
- * use the in-memory "struct proc_dir_entry" tree to parse
- * the /proc directory.
- */
-static struct file_operations proc_dir_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_readdir, /* readdir */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-struct inode_operations proc_dir_inode_operations = {
- &proc_dir_operations, /* default net directory file-ops */
- NULL, /* create */
- proc_lookup, /* lookup */
-};
-
-/*
- * /proc dynamic directories now support unlinking
- */
-struct inode_operations proc_dyna_dir_inode_operations = {
- &proc_dir_operations, /* default proc dir ops */
- NULL, /* create */
- proc_lookup, /* lookup */
- NULL, /* link */
- proc_unlink, /* unlink(struct inode *, struct dentry *) */
-};
-
-/*
- * The root /proc directory is special, as it has the
- * <pid> directories. Thus we don't use the generic
- * directory handling functions for that..
- */
-static struct file_operations proc_root_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- proc_root_readdir, /* readdir */
-};
-
-/*
- * proc root can do almost nothing..
- */
-static struct inode_operations proc_root_inode_operations = {
- &proc_root_operations, /* default base directory file-ops */
- NULL, /* create */
- proc_root_lookup, /* lookup */
-};
-
-/*
- * This is the root "inode" in the /proc tree..
- */
-struct proc_dir_entry proc_root = {
- PROC_ROOT_INO, 5, "/proc",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &proc_root_inode_operations,
- NULL, NULL,
- NULL,
- &proc_root, NULL
-};
struct proc_dir_entry *proc_net, *proc_bus, *proc_root_fs, *proc_root_driver;
-#ifdef CONFIG_MCA
-struct proc_dir_entry *proc_mca;
-#endif
-
#ifdef CONFIG_SYSCTL
struct proc_dir_entry *proc_sys_root;
#endif
-#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
-
-static int (*proc_openprom_defreaddir_ptr)(struct file *, void *, filldir_t);
-static struct dentry * (*proc_openprom_deflookup_ptr)(struct inode *, struct dentry *);
-void (*proc_openprom_use)(struct inode *, int) = 0;
-static struct openpromfs_dev *proc_openprom_devices = NULL;
-static ino_t proc_openpromdev_ino = PROC_OPENPROMD_FIRST;
-
-struct inode_operations *
-proc_openprom_register(int (*readdir)(struct file *, void *, filldir_t),
- struct dentry * (*lookup)(struct inode *, struct dentry *),
- void (*use)(struct inode *, int),
- struct openpromfs_dev ***devices)
-{
- proc_openprom_defreaddir_ptr = (proc_openprom_inode_operations.default_file_ops)->readdir;
- proc_openprom_deflookup_ptr = proc_openprom_inode_operations.lookup;
- (proc_openprom_inode_operations.default_file_ops)->readdir = readdir;
- proc_openprom_inode_operations.lookup = lookup;
- proc_openprom_use = use;
- *devices = &proc_openprom_devices;
- return &proc_openprom_inode_operations;
-}
-
-int proc_openprom_regdev(struct openpromfs_dev *d)
-{
- if (proc_openpromdev_ino == PROC_OPENPROMD_FIRST + PROC_NOPENPROMD)
- return -1;
- d->next = proc_openprom_devices;
- d->inode = proc_openpromdev_ino++;
- proc_openprom_devices = d;
- return 0;
-}
-
-int proc_openprom_unregdev(struct openpromfs_dev *d)
-{
- if (d == proc_openprom_devices) {
- proc_openprom_devices = d->next;
- } else if (!proc_openprom_devices)
- return -1;
- else {
- struct openpromfs_dev *p;
-
- for (p = proc_openprom_devices; p->next != d && p->next; p = p->next);
- if (!p->next) return -1;
- p->next = d->next;
- }
- return 0;
-}
-
-#ifdef CONFIG_SUN_OPENPROMFS_MODULE
-void
-proc_openprom_deregister(void)
-{
- (proc_openprom_inode_operations.default_file_ops)->readdir = proc_openprom_defreaddir_ptr;
- proc_openprom_inode_operations.lookup = proc_openprom_deflookup_ptr;
- proc_openprom_use = 0;
-}
-#endif
-
-#if defined(CONFIG_SUN_OPENPROMFS_MODULE) && defined(CONFIG_KMOD)
-static int
-proc_openprom_defreaddir(struct file * filp, void * dirent, filldir_t filldir)
-{
- request_module("openpromfs");
- if ((proc_openprom_inode_operations.default_file_ops)->readdir !=
- proc_openprom_defreaddir)
- return (proc_openprom_inode_operations.default_file_ops)->readdir
- (filp, dirent, filldir);
- return -EINVAL;
-}
-#define OPENPROM_DEFREADDIR proc_openprom_defreaddir
-
-static struct dentry *
-proc_openprom_deflookup(struct inode * dir, struct dentry *dentry)
-{
- request_module("openpromfs");
- if (proc_openprom_inode_operations.lookup !=
- proc_openprom_deflookup)
- return proc_openprom_inode_operations.lookup
- (dir, dentry);
- return ERR_PTR(-ENOENT);
-}
-#define OPENPROM_DEFLOOKUP proc_openprom_deflookup
-#else
-#define OPENPROM_DEFREADDIR NULL
-#define OPENPROM_DEFLOOKUP NULL
-#endif
-
-static struct file_operations proc_openprom_operations = {
- NULL, /* lseek - default */
- NULL, /* read - bad */
- NULL, /* write - bad */
- OPENPROM_DEFREADDIR, /* readdir */
-};
-
-struct inode_operations proc_openprom_inode_operations = {
- &proc_openprom_operations,/* default net directory file-ops */
- NULL, /* create */
- OPENPROM_DEFLOOKUP, /* lookup */
-};
-
-struct proc_dir_entry proc_openprom = {
- PROC_OPENPROM, 8, "openprom",
- S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
- 0, &proc_openprom_inode_operations,
- NULL, NULL,
- NULL,
- &proc_root, NULL
-};
-
-extern void openpromfs_init (void);
-#endif /* CONFIG_SUN_OPENPROMFS */
-
-static int make_inode_number(void)
-{
- int i = find_first_zero_bit((void *) proc_alloc_map, PROC_NDYNAMIC);
- if (i<0 || i>=PROC_NDYNAMIC)
- return -1;
- set_bit(i, (void *) proc_alloc_map);
- return PROC_DYNAMIC_FIRST + i;
-}
-
-int proc_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *page;
- int len = 0;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!de)
- return -ENOENT;
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
- return -ENOMEM;
-
- if (de->readlink_proc)
- len = de->readlink_proc(de, page);
-
- if (len > buflen)
- len = buflen;
-
- copy_to_user(buffer, page, len);
- free_page((unsigned long) page);
- return len;
-}
-
-struct dentry * proc_follow_link(struct dentry * dentry, struct dentry *base, unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct proc_dir_entry * de;
- char *page;
- struct dentry *d;
- int len = 0;
-
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!(page = (char*) __get_free_page(GFP_KERNEL)))
- return NULL;
-
- if (de->readlink_proc)
- len = de->readlink_proc(de, page);
-
- d = lookup_dentry(page, base, follow);
- free_page((unsigned long) page);
- return d;
-}
-
-static struct inode_operations proc_link_inode_operations = {
- NULL, /* no file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- proc_readlink, /* readlink */
- proc_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
-{
- int i;
-
- if (dp->low_ino == 0) {
- i = make_inode_number();
- if (i < 0)
- return -EAGAIN;
- dp->low_ino = i;
- }
- dp->next = dir->subdir;
- dp->parent = dir;
- dir->subdir = dp;
- if (S_ISDIR(dp->mode)) {
- if (dp->ops == NULL)
- dp->ops = &proc_dir_inode_operations;
- dir->nlink++;
- } else if (S_ISLNK(dp->mode)) {
- if (dp->ops == NULL)
- dp->ops = &proc_link_inode_operations;
- } else {
- if (dp->ops == NULL)
- dp->ops = &proc_file_inode_operations;
- }
- return 0;
-}
-
-/*
- * Kill an inode that got unregistered..
- */
-static void proc_kill_inodes(int ino)
-{
- struct list_head *p;
- struct super_block *sb;
-
- /*
- * Actually it's a partial revoke(). We have to go through all
- * copies of procfs. proc_super_blocks is protected by the big
- * lock for the time being.
- */
- for (sb = proc_super_blocks;
- sb;
- sb = (struct super_block*)sb->u.generic_sbp) {
- file_list_lock();
- for (p = sb->s_files.next; p != &sb->s_files; p = p->next) {
- struct file * filp = list_entry(p, struct file, f_list);
- struct dentry * dentry;
- struct inode * inode;
-
- dentry = filp->f_dentry;
- if (!dentry)
- continue;
- if (dentry->d_op != &proc_dentry_operations)
- continue;
- inode = dentry->d_inode;
- if (!inode)
- continue;
- if (inode->i_ino != ino)
- continue;
- filp->f_op = NULL;
- }
- file_list_unlock();
- }
-}
-
-int proc_unregister(struct proc_dir_entry * dir, int ino)
-{
- struct proc_dir_entry **p = &dir->subdir, *dp;
-
- while ((dp = *p) != NULL) {
- if (dp->low_ino == ino) {
- *p = dp->next;
- dp->next = NULL;
- if (S_ISDIR(dp->mode))
- dir->nlink--;
- if (ino >= PROC_DYNAMIC_FIRST &&
- ino < PROC_DYNAMIC_FIRST+PROC_NDYNAMIC)
- clear_bit(ino-PROC_DYNAMIC_FIRST,
- (void *) proc_alloc_map);
- proc_kill_inodes(ino);
- return 0;
- }
- p = &dp->next;
- }
- return -EINVAL;
-}
-
/*
* /proc/self:
*/
static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- int len;
char tmp[30];
-
- len = sprintf(tmp, "%d", current->pid);
- if (buflen < len)
- len = buflen;
- copy_to_user(buffer, tmp, len);
- return len;
+ sprintf(tmp, "%d", current->pid);
+ return vfs_readlink(dentry,buffer,buflen,tmp);
}
static struct dentry * proc_self_follow_link(struct dentry *dentry,
@@ -399,32 +37,13 @@ static struct dentry * proc_self_follow_link(struct dentry *dentry,
unsigned int follow)
{
char tmp[30];
-
sprintf(tmp, "%d", current->pid);
- return lookup_dentry(tmp, base, follow);
+ return vfs_follow_link(dentry,base,follow,tmp);
}
static struct inode_operations proc_self_inode_operations = {
- NULL, /* no file-ops */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- proc_self_readlink, /* readlink */
- proc_self_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: proc_self_readlink,
+ follow_link: proc_self_follow_link
};
static struct proc_dir_entry proc_root_self = {
@@ -435,7 +54,7 @@ static struct proc_dir_entry proc_root_self = {
#ifdef __powerpc__
static struct proc_dir_entry proc_root_ppc_htab = {
0, 8, "ppc_htab",
- S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
+ S_IFREG | S_IRUGO|S_IWUSR, 1, 0, 0,
0, &proc_ppc_htab_inode_operations,
};
#endif
@@ -444,23 +63,21 @@ void __init proc_root_init(void)
{
proc_misc_init();
proc_register(&proc_root, &proc_root_self);
- proc_net = create_proc_entry("net", S_IFDIR, 0);
+ proc_net = proc_mkdir("net", 0);
#ifdef CONFIG_SYSVIPC
- create_proc_entry("sysvipc", S_IFDIR, 0);
+ proc_mkdir("sysvipc", 0);
#endif
#ifdef CONFIG_SYSCTL
- proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
+ proc_sys_root = proc_mkdir("sys", 0);
#endif
-#ifdef CONFIG_MCA
- proc_mca = create_proc_entry("mca", S_IFDIR, 0);
-#endif
- proc_root_fs = create_proc_entry("fs", S_IFDIR, 0);
- proc_root_driver = create_proc_entry("driver", S_IFDIR, 0);
+ proc_root_fs = proc_mkdir("fs", 0);
+ proc_root_driver = proc_mkdir("driver", 0);
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
#ifdef CONFIG_SUN_OPENPROMFS
openpromfs_init ();
#endif
- proc_register(&proc_root, &proc_openprom);
+ /* just give it a mountpoint */
+ proc_mkdir("openprom", 0);
#endif
proc_tty_init();
#ifdef __powerpc__
@@ -469,63 +86,7 @@ void __init proc_root_init(void)
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
- proc_bus = create_proc_entry("bus", S_IFDIR, 0);
-}
-
-/*
- * As some entries in /proc are volatile, we want to
- * get rid of unused dentries. This could be made
- * smarter: we could keep a "volatile" flag in the
- * inode to indicate which ones to keep.
- */
-static void
-proc_delete_dentry(struct dentry * dentry)
-{
- d_drop(dentry);
-}
-
-struct dentry_operations proc_dentry_operations =
-{
- NULL, /* revalidate */
- NULL, /* d_hash */
- NULL, /* d_compare */
- proc_delete_dentry /* d_delete(struct dentry *) */
-};
-
-/*
- * Don't create negative dentries here, return -ENOENT by hand
- * instead.
- */
-struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
-{
- struct inode *inode;
- struct proc_dir_entry * de;
- int error;
-
- error = -ENOENT;
- inode = NULL;
- de = (struct proc_dir_entry *) dir->u.generic_ip;
- if (de) {
- for (de = de->subdir; de ; de = de->next) {
- if (!de || !de->low_ino)
- continue;
- if (de->namelen != dentry->d_name.len)
- continue;
- if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
- int ino = de->low_ino;
- error = -EINVAL;
- inode = proc_get_inode(dir->i_sb, ino, de);
- break;
- }
- }
- }
-
- if (inode) {
- dentry->d_op = &proc_dentry_operations;
- d_add(dentry, inode);
- return NULL;
- }
- return ERR_PTR(error);
+ proc_bus = proc_mkdir("bus", 0);
}
static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
@@ -564,63 +125,6 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
return proc_pid_lookup(dir, dentry);
}
-/*
- * This returns non-zero if at EOF, so that the /proc
- * root directory can use this and check if it should
- * continue with the <pid> entries..
- *
- * Note that the VFS-layer doesn't care about the return
- * value of the readdir() call, as long as it's non-negative
- * for success..
- */
-int proc_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- struct proc_dir_entry * de;
- unsigned int ino;
- int i;
- struct inode *inode = filp->f_dentry->d_inode;
-
- ino = inode->i_ino;
- de = (struct proc_dir_entry *) inode->u.generic_ip;
- if (!de)
- return -EINVAL;
- i = filp->f_pos;
- switch (i) {
- case 0:
- if (filldir(dirent, ".", 1, i, ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- case 1:
- if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
- return 0;
- i++;
- filp->f_pos++;
- /* fall through */
- default:
- de = de->subdir;
- i -= 2;
- for (;;) {
- if (!de)
- return 1;
- if (!i)
- break;
- de = de->next;
- i--;
- }
-
- do {
- if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino) < 0)
- return 0;
- filp->f_pos++;
- de = de->next;
- } while (de);
- }
- return 1;
-}
-
static int proc_root_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
@@ -636,14 +140,35 @@ static int proc_root_readdir(struct file * filp,
return proc_pid_readdir(filp, dirent, filldir);
}
-static int proc_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct proc_dir_entry * dp = dir->u.generic_ip;
+/*
+ * The root /proc directory is special, as it has the
+ * <pid> directories. Thus we don't use the generic
+ * directory handling functions for that..
+ */
+static struct file_operations proc_root_operations = {
+ NULL, /* lseek - default */
+ NULL, /* read - bad */
+ NULL, /* write - bad */
+ proc_root_readdir, /* readdir */
+};
-printk("proc_file_unlink: deleting %s/%s\n", dp->name, dentry->d_name.name);
+/*
+ * proc root can do almost nothing..
+ */
+static struct inode_operations proc_root_inode_operations = {
+ &proc_root_operations, /* default base directory file-ops */
+ NULL, /* create */
+ proc_root_lookup, /* lookup */
+};
- remove_proc_entry(dentry->d_name.name, dp);
- dentry->d_inode->i_nlink = 0;
- d_delete(dentry);
- return 0;
-}
+/*
+ * This is the root "inode" in the /proc tree..
+ */
+struct proc_dir_entry proc_root = {
+ PROC_ROOT_INO, 5, "/proc",
+ S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+ 0, &proc_root_inode_operations,
+ NULL, NULL,
+ NULL,
+ &proc_root, NULL
+};
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 0fbae7262..810c3accd 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -122,9 +122,7 @@ struct inode_operations qnx4_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/qnx4/file.c b/fs/qnx4/file.c
index 2e2b9c2fb..49ea90921 100644
--- a/fs/qnx4/file.c
+++ b/fs/qnx4/file.c
@@ -34,7 +34,7 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
-static int qnx4_readpage(struct file *file, struct page *page);
+static int qnx4_readpage(struct dentry *dentry, struct page *page);
#ifdef CONFIG_QNX4FS_RW
static ssize_t qnx4_file_write(struct file *filp, const char *buf,
@@ -192,20 +192,17 @@ struct inode_operations qnx4_file_inode_operations =
qnx4_bmap, /* get_block */
qnx4_readpage, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
#ifdef CONFIG_QNX4FS_RW
qnx4_truncate, /* truncate */
#else
NULL,
#endif
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
-static int qnx4_readpage(struct file *file, struct page *page)
+static int qnx4_readpage(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
struct qnx4_inode_info *qnx4_ino = &inode->u.qnx4_i;
unsigned long buf;
@@ -215,18 +212,17 @@ static int qnx4_readpage(struct file *file, struct page *page)
struct buffer_head *bh;
int res = -EIO;
- QNX4DEBUG(("qnx4: readpage offset=[%ld]\n", (long) page->offset));
+ QNX4DEBUG(("qnx4: readpage index=[%ld]\n", (long) page->index));
if (qnx4_ino->i_xblk != 0) {
printk("qnx4: sorry, this file is extended, don't know how to handle it (yet) !\n");
return -EIO;
}
atomic_inc(&page->count);
- set_bit(PG_locked, &page->flags);
buf = page_address(page);
clear_bit(PG_uptodate, &page->flags);
clear_bit(PG_error, &page->flags);
- offset = page->offset;
+ offset = page->index<<PAGE_SHIFT;
if (offset < inode->i_size) {
res = 0;
@@ -253,8 +249,7 @@ static int qnx4_readpage(struct file *file, struct page *page)
} else {
set_bit(PG_uptodate, &page->flags);
}
- clear_bit(PG_locked, &page->flags);
- wake_up(&page->wait);
+ Unlock_Page(page);
/* free_page(buf); */
return res;
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 3acd5e028..e75c4d93e 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -72,14 +72,6 @@ static void qnx4_write_super(struct super_block *sb)
sb->s_dirt = 0;
}
-static void qnx4_put_inode(struct inode *inode)
-{
- if (inode->i_nlink != 0) {
- return;
- }
- inode->i_size = 0;
-}
-
static void qnx4_write_inode(struct inode *inode)
{
struct qnx4_inode_entry *raw_inode;
@@ -134,15 +126,13 @@ static struct super_operations qnx4_sops =
#else
NULL,
#endif
+ NULL, /* put_inode */
#ifdef CONFIG_QNX4FS_RW
- qnx4_put_inode,
qnx4_delete_inode,
- NULL, /* notify_change */
#else
- NULL, /* put_inode */
NULL, /* delete_inode */
- NULL, /* notify_change */
#endif
+ NULL, /* notify_change */
qnx4_put_super,
#ifdef CONFIG_QNX4FS_RW
qnx4_write_super,
diff --git a/fs/qnx4/symlinks.c b/fs/qnx4/symlinks.c
index 0b3f9ae03..ed7cdfca6 100644
--- a/fs/qnx4/symlinks.c
+++ b/fs/qnx4/symlinks.c
@@ -46,10 +46,8 @@ struct inode_operations qnx4_symlink_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index 7cb561704..287f4f60b 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -407,9 +407,8 @@ out: return ERR_PTR(res);
*/
static int
-romfs_readpage(struct file * file, struct page * page)
+romfs_readpage(struct dentry * dentry, struct page * page)
{
- struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
unsigned long buf;
unsigned long offset, avail, readlen;
@@ -445,63 +444,6 @@ romfs_readpage(struct file * file, struct page * page)
return result;
}
-static int
-romfs_readlink(struct dentry *dentry, char *buffer, int len)
-{
- struct inode *inode = dentry->d_inode;
- int mylen;
- char buf[ROMFS_MAXFN]; /* XXX dynamic */
-
- if (!inode || !S_ISLNK(inode->i_mode)) {
- mylen = -EBADF;
- goto out;
- }
-
- mylen = min(sizeof(buf), inode->i_size);
-
- if (romfs_copyfrom(inode, buf, inode->u.romfs_i.i_dataoffset, mylen) <= 0) {
- mylen = -EIO;
- goto out;
- }
- copy_to_user(buffer, buf, mylen);
-
-out:
- return mylen;
-}
-
-static struct dentry *romfs_follow_link(struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- char *link;
- int len, cnt;
-
- len = inode->i_size;
-
- dentry = ERR_PTR(-EAGAIN); /* correct? */
- if (!(link = kmalloc(len+1, GFP_KERNEL)))
- goto outnobuf;
-
- cnt = romfs_copyfrom(inode, link, inode->u.romfs_i.i_dataoffset, len);
- if (len != cnt) {
- dentry = ERR_PTR(-EIO);
- goto out;
- } else
- link[len] = 0;
-
- dentry = lookup_dentry(link, base, follow);
- kfree(link);
-
- if (0) {
-out:
- kfree(link);
-outnobuf:
- dput(base);
- }
- return dentry;
-}
-
/* Mapping from our types to the kernel */
static struct file_operations romfs_file_operations = {
@@ -537,10 +479,8 @@ static struct inode_operations romfs_file_inode_operations = {
NULL, /* get_block -- not really */
romfs_readpage, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -581,34 +521,15 @@ static struct inode_operations romfs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
static struct inode_operations romfs_link_inode_operations = {
- NULL, /* no file operations on symlinks */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- romfs_readlink, /* readlink */
- romfs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: romfs_readpage
};
static mode_t romfs_modemap[] =
diff --git a/fs/smbfs/cache.c b/fs/smbfs/cache.c
index 17251b80b..46354e5a5 100644
--- a/fs/smbfs/cache.c
+++ b/fs/smbfs/cache.c
@@ -38,102 +38,54 @@ printk_name(const char *name, int len)
}
#endif
-/*
- * Get a page for this inode, if new is set then we want to allocate
- * the page if it isn't in memory. As I understand it the rest of the
- * smb-cache code assumes we return a locked page.
- */
-static unsigned long
-get_cached_page(struct address_space *mapping, unsigned long offset, int new)
-{
- struct page * page;
- struct page ** hash;
- struct page *cached_page = NULL;
-
- again:
- hash = page_hash(mapping, offset);
- page = __find_lock_page(mapping, offset, hash);
- if(!page && new) {
- /* not in cache, alloc a new page if we didn't do it yet */
- if (!cached_page) {
- cached_page = page_cache_alloc();
- if (!cached_page)
- return 0;
- /* smb code assumes pages are zeroed */
- clear_page(page_address(cached_page));
- goto again;
- }
- page = cached_page;
- if (page->buffers)
- BUG();
- printk(KERN_DEBUG "smbfs: get_cached_page\n");
- if (add_to_page_cache_unique(page, mapping, offset, hash))
- /* Hmm, a page has materialized in the
- cache. Fine. Go back and get that page
- instead... */
- goto again;
- cached_page = NULL;
- }
- printk(KERN_DEBUG "smbfs: get_cached_page done\n");
- if (cached_page)
- page_cache_free(cached_page);
- if(!page)
- return 0;
- if(!PageLocked(page))
- BUG();
- return page_address(page);
-}
-
static inline struct address_space *
get_cache_inode(struct cache_head *cachep)
{
- return (mem_map + MAP_NR((unsigned long) cachep))->mapping;
+ return page_cache_entry((unsigned long) cachep)->mapping;
}
/*
- * Get a pointer to the cache_head structure,
- * mapped as the page at offset 0. The page is
- * kept locked while we're using the cache.
+ * Try to reassemble the old dircache. If we fail - set ->valid to 0.
+ * In any case, get at least the page at offset 0 (with ->valid==0 if
+ * the old one didn't make it, indeed).
*/
struct cache_head *
smb_get_dircache(struct dentry * dentry)
{
struct address_space * mapping = &dentry->d_inode->i_data;
- struct cache_head * cachep;
+ struct cache_head * cachep = NULL;
+ struct page *page;
-#ifdef SMBFS_DEBUG_VERBOSE
- printk("smb_get_dircache: finding cache for %s/%s\n",
- dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
- cachep = (struct cache_head *) get_cached_page(mapping, 0, 1);
- if (!cachep)
+ page = find_lock_page(mapping, 0);
+ if (!page) {
+ /* Sorry, not even page 0 around */
+ page = grab_cache_page(mapping, 0);
+ if (!page)
+ goto out;
+ cachep = (struct cache_head *)kmap(page);
+ memset((char*)cachep, 0, PAGE_SIZE);
goto out;
- if (cachep->valid)
- {
+ }
+ cachep = (struct cache_head *)kmap(page);
+ if (cachep->valid) {
+ /*
+ * OK, at least the page 0 survived and seems to be promising.
+ * Let's try to reassemble the rest.
+ */
struct cache_index * index = cachep->index;
- struct cache_block * block;
unsigned long offset;
int i;
- cachep->valid = 0;
- /*
- * Here we only want to find existing cache blocks,
- * not add new ones.
- */
- for (i = 0; i < cachep->pages; i++, index++) {
-#ifdef SMBFS_PARANOIA
-if (index->block)
-printk("smb_get_dircache: cache %s/%s has existing block!\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
- offset = PAGE_SIZE + (i << PAGE_SHIFT);
- block = (struct cache_block *) get_cached_page(mapping,
- offset, 0);
- if (!block)
+ for (offset = 0, i = 0; i < cachep->pages; i++, index++) {
+ offset += PAGE_SIZE;
+ page = find_lock_page(mapping,offset>>PAGE_CACHE_SHIFT);
+ if (!page) {
+ /* Alas, poor Yorick */
+ cachep->valid = 0;
goto out;
- index->block = block;
+ }
+ index->block = (struct cache_block *) kmap(page);
}
- cachep->valid = 1;
}
out:
return cachep;
@@ -146,18 +98,20 @@ static void
smb_free_cache_blocks(struct cache_head * cachep)
{
struct cache_index * index = cachep->index;
+ struct page * page;
int i;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_free_cache_blocks: freeing %d blocks\n", cachep->pages);
#endif
- for (i = 0; i < cachep->pages; i++, index++)
- {
- if (index->block)
- {
- put_cached_page((unsigned long) index->block);
- index->block = NULL;
- }
+ for (i = 0; i < cachep->pages; i++, index++) {
+ if (!index->block)
+ continue;
+ page = page_cache_entry((unsigned long) index->block);
+ index->block = NULL;
+ kunmap(page);
+ UnlockPage(page);
+ page_cache_release(page);
}
}
@@ -167,11 +121,15 @@ printk("smb_free_cache_blocks: freeing %d blocks\n", cachep->pages);
void
smb_free_dircache(struct cache_head * cachep)
{
+ struct page *page;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_free_dircache: freeing cache\n");
#endif
smb_free_cache_blocks(cachep);
- put_cached_page((unsigned long) cachep);
+ page = page_cache_entry((unsigned long) cachep);
+ kunmap(page);
+ UnlockPage(page);
+ page_cache_release(page);
}
/*
@@ -199,6 +157,7 @@ smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
struct address_space * mapping = get_cache_inode(cachep);
struct cache_index * index;
struct cache_block * block;
+ struct page *page;
unsigned long page_off;
unsigned int nent, offset, len = entry->len;
unsigned int needed = len + sizeof(struct cache_entry);
@@ -220,8 +179,7 @@ printk(" at %ld\n", fpos);
goto get_block;
/* space available? */
- if (needed < index->space)
- {
+ if (needed < index->space) {
add_entry:
nent = index->num_entries;
index->num_entries++;
@@ -249,26 +207,17 @@ len, fpos, cachep->entries);
if (cachep->idx > NINDEX) /* not likely */
goto out_full;
index++;
-#ifdef SMBFS_PARANOIA
-if (index->block)
-printk("smb_add_to_cache: new index already has block!\n");
-#endif
-
/*
- * Get the next cache block
+ * Get the next cache block. We don't care for its contents.
*/
get_block:
cachep->pages++;
page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT);
- block = (struct cache_block *) get_cached_page(mapping, page_off, 1);
- if (block)
- {
+ page = grab_cache_page(mapping, page_off>>PAGE_CACHE_SHIFT);
+ if (page) {
+ block = (struct cache_block *)kmap(page);
index->block = block;
index->space = PAGE_SIZE;
-#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_add_to_cache: mapping=%p, pages=%d, block at %ld\n",
-mapping, cachep->pages, page_off);
-#endif
goto add_entry;
}
/*
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index cbaa646b3..37bf168f6 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -62,10 +62,8 @@ struct inode_operations smb_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
smb_revalidate_inode, /* revalidate */
};
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index 7ef18302f..189c853f9 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -97,10 +97,9 @@ io_error:
return result;
}
-int
-smb_readpage(struct file *file, struct page *page)
+static int
+smb_readpage(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
int error;
pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
@@ -168,9 +167,8 @@ printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
* We are called with the page locked and the caller unlocks.
*/
static int
-smb_writepage(struct file *file, struct page *page)
+smb_writepage(struct dentry *dentry, struct page *page)
{
- struct dentry *dentry = file->f_dentry;
int result;
#ifdef SMBFS_PARANOIA
@@ -403,9 +401,7 @@ struct inode_operations smb_file_inode_operations =
NULL, /* get_block */
smb_readpage, /* readpage */
smb_writepage, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
smb_file_permission, /* permission */
- NULL, /* smap */
smb_revalidate_inode, /* revalidate */
};
diff --git a/fs/super.c b/fs/super.c
index 9c8459248..9f901236b 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -58,10 +58,9 @@ int nr_super_blocks = 0;
int max_super_blocks = NR_SUPER;
LIST_HEAD(super_blocks);
-static struct file_system_type *file_systems = (struct file_system_type *) NULL;
-struct vfsmount *vfsmntlist = (struct vfsmount *) NULL;
-static struct vfsmount *vfsmnttail = (struct vfsmount *) NULL,
- *mru_vfsmnt = (struct vfsmount *) NULL;
+static struct file_system_type *file_systems = NULL;
+struct vfsmount *vfsmntlist = NULL;
+static struct vfsmount *vfsmnttail = NULL, *mru_vfsmnt = NULL;
/*
* This part handles the management of the list of mounted filesystems.
@@ -70,23 +69,19 @@ struct vfsmount *lookup_vfsmnt(kdev_t dev)
{
struct vfsmount *lptr;
- if (vfsmntlist == (struct vfsmount *)NULL)
- return ((struct vfsmount *)NULL);
+ if (vfsmntlist == NULL)
+ return NULL;
- if (mru_vfsmnt != (struct vfsmount *)NULL &&
- mru_vfsmnt->mnt_dev == dev)
+ if (mru_vfsmnt != NULL && mru_vfsmnt->mnt_dev == dev)
return (mru_vfsmnt);
- for (lptr = vfsmntlist;
- lptr != (struct vfsmount *)NULL;
- lptr = lptr->mnt_next)
+ for (lptr = vfsmntlist; lptr != NULL; lptr = lptr->mnt_next)
if (lptr->mnt_dev == dev) {
mru_vfsmnt = lptr;
return (lptr);
}
- return ((struct vfsmount *)NULL);
- /* NOTREACHED */
+ return NULL;
}
static struct vfsmount *add_vfsmnt(struct super_block *sb,
@@ -104,7 +99,8 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb,
lptr->mnt_dev = sb->s_dev;
lptr->mnt_flags = sb->s_flags;
- sema_init(&lptr->mnt_dquot.semaphore, 1);
+ sema_init(&lptr->mnt_dquot.dqio_sem, 1);
+ sema_init(&lptr->mnt_dquot.dqoff_sem, 1);
lptr->mnt_dquot.flags = 0;
/* N.B. Is it really OK to have a vfsmount without names? */
@@ -139,7 +135,7 @@ void remove_vfsmnt(kdev_t dev)
{
struct vfsmount *lptr, *tofree;
- if (vfsmntlist == (struct vfsmount *)NULL)
+ if (vfsmntlist == NULL)
return;
lptr = vfsmntlist;
if (lptr->mnt_dev == dev) {
@@ -148,13 +144,13 @@ void remove_vfsmnt(kdev_t dev)
if (vfsmnttail->mnt_dev == dev)
vfsmnttail = vfsmntlist;
} else {
- while (lptr->mnt_next != (struct vfsmount *)NULL) {
+ while (lptr->mnt_next != NULL) {
if (lptr->mnt_next->mnt_dev == dev)
break;
lptr = lptr->mnt_next;
}
tofree = lptr->mnt_next;
- if (tofree == (struct vfsmount *)NULL)
+ if (tofree == NULL)
return;
lptr->mnt_next = lptr->mnt_next->mnt_next;
if (vfsmnttail->mnt_dev == dev)
@@ -566,7 +562,6 @@ static struct super_block * read_super(kdev_t dev,const char *name,int flags,
if (!type->read_super(s, data, silent))
goto out_fail;
s->s_dev = dev; /* N.B. why do this again?? */
- s->s_rd_only = 0;
s->s_type = type;
out:
return s;
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index d76f1d6b3..f17fb8b63 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -62,10 +62,8 @@ struct inode_operations sysv_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/sysv/file.c b/fs/sysv/file.c
index 36650f141..f54b8d6bc 100644
--- a/fs/sysv/file.c
+++ b/fs/sysv/file.c
@@ -77,9 +77,7 @@ struct inode_operations sysv_file_inode_operations = {
sysv_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
sysv_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
index 1db8ca9c8..6cd146dbd 100644
--- a/fs/sysv/inode.c
+++ b/fs/sysv/inode.c
@@ -21,6 +21,7 @@
* the superblock.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/sched.h>
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index 2a1626bdd..844912898 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -440,59 +440,41 @@ end_unlink:
int sysv_symlink(struct inode * dir, struct dentry * dentry,
const char * symname)
{
- struct sysv_dir_entry * de;
struct inode * inode;
- struct buffer_head * name_block;
- char * name_block_data;
- struct super_block * sb;
- int i;
- char c;
+ struct sysv_dir_entry * de;
struct buffer_head * bh;
-
+ int err;
+ int l;
+
+ err = -ENAMETOOLONG;
+ l = strlen(symname)+1;
+ if (l > dir->i_sb->sv_block_size_1)
+ goto out;
+ err = -ENOSPC;
if (!(inode = sysv_new_inode(dir)))
- return -ENOSPC;
+ goto out;
inode->i_mode = S_IFLNK | 0777;
inode->i_op = &sysv_symlink_inode_operations;
- name_block = sysv_file_bread(inode, 0, 1);
- if (!name_block) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- return -ENOSPC;
- }
- sb = inode->i_sb;
- name_block_data = name_block->b_data;
- i = 0;
- while (i < sb->sv_block_size_1 && (c = *(symname++)))
- name_block_data[i++] = c;
- name_block_data[i] = 0;
- mark_buffer_dirty(name_block, 1);
- brelse(name_block);
- inode->i_size = i;
+ err = block_symlink(inode, symname, l);
+ if (err)
+ goto out_no_entry;
mark_inode_dirty(inode);
- bh = sysv_find_entry(dir, dentry->d_name.name,
- dentry->d_name.len, &de);
- if (bh) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- brelse(bh);
- return -EEXIST;
- }
- i = sysv_add_entry(dir, dentry->d_name.name,
+ err = sysv_add_entry(dir, dentry->d_name.name,
dentry->d_name.len, &bh, &de);
- if (i) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput(inode);
- return i;
- }
+ if (err)
+ goto out_no_entry;
de->inode = inode->i_ino;
mark_buffer_dirty(bh, 1);
brelse(bh);
d_instantiate(dentry, inode);
- return 0;
+out:
+ return err;
+out_no_entry:
+ inode->i_nlink--;
+ mark_inode_dirty(inode);
+ iput(inode);
+ goto out;
}
int sysv_link(struct dentry * old_dentry, struct inode * dir,
diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
index df611d589..3f77f831e 100644
--- a/fs/sysv/symlink.c
+++ b/fs/sysv/symlink.c
@@ -13,79 +13,14 @@
* SystemV/Coherent symlink handling code
*/
-#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/sysv_fs.h>
-#include <linux/stat.h>
-
-#include <asm/uaccess.h>
-
-static int sysv_readlink(struct dentry *, char *, int);
-static struct dentry *sysv_follow_link(struct dentry *, struct dentry *, unsigned int);
/*
* symlinks can't do much...
*/
struct inode_operations sysv_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- sysv_readlink, /* readlink */
- sysv_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: sysv_get_block,
+ readpage: block_read_full_page
};
-
-static struct dentry *sysv_follow_link(struct dentry * dentry,
- struct dentry * base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head * bh;
-
- bh = sysv_file_bread(inode, 0, 0);
- if (!bh) {
- dput(base);
- return ERR_PTR(-EIO);
- }
- UPDATE_ATIME(inode);
- base = lookup_dentry(bh->b_data, base, follow);
- brelse(bh);
- return base;
-}
-
-static int sysv_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head * bh;
- char * bh_data;
- int i;
- char c;
-
- if (buflen > inode->i_sb->sv_block_size_1)
- buflen = inode->i_sb->sv_block_size_1;
- bh = sysv_file_bread(inode, 0, 0);
- if (!bh)
- return 0;
- bh_data = bh->b_data;
- i = 0;
- while (i<buflen && (c = bh_data[i])) {
- i++;
- put_user(c,buffer++);
- }
- brelse(bh);
- return i;
-}
diff --git a/fs/sysv/truncate.c b/fs/sysv/truncate.c
index db0f72506..32bfccf6d 100644
--- a/fs/sysv/truncate.c
+++ b/fs/sysv/truncate.c
@@ -36,7 +36,7 @@
*/
#define DATA_BUFFER_USED(bh) \
- (atomic_read(&bh->b_count) || buffer_locked(bh))
+ (atomic_read(&bh->b_count)>1 || buffer_locked(bh))
/* We throw away any data beyond inode->i_size. */
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index f5ab39437..03e66fe23 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -34,6 +34,56 @@
#include "udf_i.h"
#include "udf_sb.h"
+#define udf_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
+#define udf_set_bit(nr,addr) ext2_set_bit(nr,addr)
+#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
+#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
+#define udf_find_next_one_bit(addr, size, offset) find_next_one_bit(addr, size, offset)
+
+#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
+#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
+#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
+
+extern inline int find_next_one_bit (void * addr, int size, int offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= (BITS_PER_LONG-1);
+ if (offset)
+ {
+ tmp = leBPL_to_cpup(p++);
+ tmp &= ~0UL << offset;
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1))
+ {
+ if ((tmp = leBPL_to_cpup(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = leBPL_to_cpup(p);
+found_first:
+ tmp &= ~0UL >> (BITS_PER_LONG-size);
+found_middle:
+ return result + ffz(~tmp);
+}
+
+#define find_first_one_bit(addr, size)\
+ find_next_one_bit((addr), (size), 0)
+
static int read_block_bitmap(struct super_block * sb, unsigned int block,
unsigned long bitmap_nr)
{
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 000ef6481..84218eb14 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -32,6 +32,7 @@
#include "udfdecl.h"
#if defined(__linux__) && defined(__KERNEL__)
+#include <linux/config.h>
#include <linux/version.h>
#include "udf_i.h"
#include "udf_sb.h"
@@ -96,10 +97,8 @@ struct inode_operations udf_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -158,13 +157,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
struct FileIdentDesc *fi=NULL;
struct FileIdentDesc cfi;
int block, iblock;
- int nf_pos = filp->f_pos;
+ loff_t nf_pos = filp->f_pos;
int flen;
char fname[255];
char *nameptr;
Uint16 liu;
Uint8 lfi;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
struct buffer_head * bh = NULL;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
@@ -276,10 +275,6 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
return 1; /* halt enum */
}
}
- else
- {
- udf_debug("size=%d, nf_pos=%d, liu=%d, lfi=%d\n", size, nf_pos, liu, lfi);
- }
}
} /* end while */
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 7ea1ac38e..b8a94e8f5 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -17,7 +17,6 @@
*/
#include "udfdecl.h"
-#include "udf_sb.h"
#if defined(__linux__) && defined(__KERNEL__)
@@ -85,7 +84,7 @@ Uint8 * udf_filead_read(struct inode *dir, Uint8 *tmpad, Uint8 ad_size,
}
struct FileIdentDesc *
-udf_fileident_read(struct inode *dir, int *nf_pos,
+udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
struct FileIdentDesc *cfi,
lb_addr *bloc, Uint32 *extoffset,
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 0a9642b08..2e17d81d4 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -31,6 +31,7 @@
*/
#include "udfdecl.h"
+#include <linux/config.h>
#include <linux/fs.h>
#include <linux/udf_fs.h>
#include <asm/uaccess.h>
@@ -42,11 +43,7 @@
#include "udf_i.h"
#include "udf_sb.h"
-#define NBUF 32
-
-typedef void * poll_table;
-
-static long long udf_file_llseek(struct file *, long long, int);
+static loff_t udf_file_llseek(struct file *, loff_t, int);
static ssize_t udf_file_read_adinicb (struct file *, char *, size_t, loff_t *);
static ssize_t udf_file_write (struct file *, const char *, size_t, loff_t *);
#if BITS_PER_LONG < 64
@@ -92,14 +89,12 @@ struct inode_operations udf_file_inode_operations = {
udf_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
#ifdef CONFIG_UDF_RW
udf_truncate, /* truncate */
#else
NULL, /* truncate */
#endif
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
@@ -137,21 +132,19 @@ struct inode_operations udf_file_inode_operations_adinicb = {
udf_get_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
#ifdef CONFIG_UDF_RW
udf_truncate, /* truncate */
#else
NULL, /* truncate */
#endif
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
/*
* Make sure the offset never goes beyond the 32-bit mark..
*/
-static long long udf_file_llseek(struct file * file, long long offset, int origin)
+static loff_t udf_file_llseek(struct file * file, loff_t offset, int origin)
{
struct inode * inode = file->f_dentry->d_inode;
@@ -168,12 +161,6 @@ static long long udf_file_llseek(struct file * file, long long offset, int origi
break;
}
}
-#if BITS_PER_LONG < 64
- if (((unsigned long long) offset >> 32) != 0)
- {
- return -EINVAL;
- }
-#endif
if (offset != file->f_pos)
{
file->f_pos = offset;
@@ -271,7 +258,8 @@ static ssize_t udf_file_read_adinicb(struct file * filp, char * buf,
size_t bufsize, loff_t * loff)
{
struct inode *inode = filp->f_dentry->d_inode;
- Uint32 size, left, pos, block;
+ loff_t size, left, pos;
+ Uint32 block;
struct buffer_head *bh = NULL;
size = inode->i_size;
@@ -453,7 +441,7 @@ static int udf_release_file(struct inode * inode, struct file * filp)
*/
static int udf_open_file(struct inode * inode, struct file * filp)
{
- if (inode->i_size == (Uint32)-1 && (filp->f_mode & FMODE_WRITE))
+ if ((inode->i_size & 0xFFFFFFFF00000000UL) && !(filp->f_flags & O_LARGEFILE))
return -EFBIG;
return 0;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 71083a7bd..05e03def5 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -201,8 +201,8 @@ struct buffer_head * udf_expand_adinicb(struct inode *inode, int *block, int isd
if (isdir)
{
struct udf_fileident_bh sfibh, dfibh;
- int f_pos = UDF_I_EXT0OFFS(inode) >> 2;
- int size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2;
+ loff_t f_pos = UDF_I_EXT0OFFS(inode) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(inode) + inode->i_size) >> 2;
struct FileIdentDesc cfi, *sfi, *dfi;
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
@@ -383,7 +383,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
pextoffset = cextoffset;
cextoffset = nextoffset;
-
+
if ((etype = udf_next_aext(inode, &cbloc, &nextoffset, &eloc, &elen, &cbh, 1)) == -1)
break;
@@ -701,14 +701,31 @@ static void udf_merge_extents(struct inode *inode,
(((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits)))
{
- laarr[i].extLength = laarr[i+1].extLength +
- (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
- inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
- if (*endnum > (i+2))
- memmove(&laarr[i+1], &laarr[i+2],
- sizeof(long_ad) * (*endnum - (i+2)));
- i --;
- (*endnum) --;
+ if (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ (laarr[i+1].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) & ~UDF_EXTENT_LENGTH_MASK)
+ {
+ laarr[i+1].extLength = (laarr[i+1].extLength -
+ (laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ UDF_EXTENT_LENGTH_MASK) & ~(inode->i_sb->s_blocksize-1);
+ laarr[i].extLength = (UDF_EXTENT_LENGTH_MASK + 1) -
+ inode->i_sb->s_blocksize;
+ laarr[i+1].extLocation.logicalBlockNum =
+ laarr[i].extLocation.logicalBlockNum +
+ ((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) >>
+ inode->i_sb->s_blocksize_bits);
+ }
+ else
+ {
+ laarr[i].extLength = laarr[i+1].extLength +
+ (((laarr[i].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize-1));
+ if (*endnum > (i+2))
+ memmove(&laarr[i+1], &laarr[i+2],
+ sizeof(long_ad) * (*endnum - (i+2)));
+ i --;
+ (*endnum) --;
+ }
}
}
}
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index 635ab1b79..0f763b5d1 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -123,7 +123,7 @@ udf_get_last_block(kdev_t dev, int *flags)
BLKGETSIZE,
(unsigned long) &lblock);
- if (!ret) /* Hard Disk */
+ if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
{
if (mult)
lblock *= mult;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 712cf09fb..ea921eeb3 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -25,6 +25,8 @@
*
*/
+#include "udfdecl.h"
+
#if defined(__linux__) && defined(__KERNEL__)
#include <linux/version.h>
#include "udf_i.h"
@@ -36,8 +38,6 @@
#include <linux/udf_fs.h>
#endif
-#include "udfdecl.h"
-
static inline int udf_match(int len, const char * const name, struct qstr *qs)
{
if (len != qs->len)
@@ -147,13 +147,13 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
struct FileIdentDesc *cfi)
{
struct FileIdentDesc *fi=NULL;
- int f_pos, block;
- int flen;
+ loff_t f_pos;
+ int block, flen;
char fname[255];
char *nameptr;
Uint8 lfi;
Uint16 liu;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
struct buffer_head *bh = NULL;
@@ -333,10 +333,10 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
struct ustr unifilename;
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen;
- int f_pos;
+ loff_t f_pos;
int flen;
char *nameptr;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
int nfidlen;
Uint8 lfi;
Uint16 liu;
@@ -492,7 +492,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
extoffset -= sizeof(long_ad);
}
- dir->i_size += nfidlen;
if (sb->s_blocksize - fibh->eoffset >= nfidlen)
{
fibh->soffset = fibh->eoffset;
@@ -550,8 +549,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
else
{
elen = ((elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
+ block = eloc.logicalBlockNum +
+ ((elen - 1) >> dir->i_sb->s_blocksize_bits);
elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 0);
}
@@ -568,11 +567,30 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) ==
EXTENT_RECORDED_ALLOCATED)
{
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
+ if (block == (eloc.logicalBlockNum +
+ ((elen - 1) >> dir->i_sb->s_blocksize_bits)))
+ {
+ if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) !=
+ EXTENT_RECORDED_ALLOCATED)
+ {
+ udf_release_data(bh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(fibh->ebh);
+ udf_debug("next extent not recorded and allocated\n");
+ return NULL;
+ }
+ }
}
else
- block ++;
+ {
+ udf_release_data(bh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(fibh->ebh);
+ udf_debug("next extent not recorded and allocated\n");
+ return NULL;
+ }
+ block = eloc.logicalBlockNum + ((elen - 1) >>
+ dir->i_sb->s_blocksize_bits);
}
fi = (struct FileIdentDesc *)(fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
@@ -586,6 +604,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (!udf_write_fi(cfi, fi, fibh, NULL, name))
{
udf_release_data(bh);
+ dir->i_size += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
UDF_I_LENALLOC(dir) += nfidlen;
dir->i_version = ++event;
@@ -595,7 +614,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
else
{
udf_release_data(bh);
- dir->i_size -= nfidlen;
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
@@ -807,8 +825,8 @@ static int empty_dir(struct inode *dir)
{
struct FileIdentDesc *fi, cfi;
struct udf_fileident_bh fibh;
- int f_pos;
- int size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
+ loff_t f_pos;
+ loff_t size = (UDF_I_EXT0OFFS(dir) + dir->i_size) >> 2;
int block;
lb_addr bloc, eloc;
Uint32 extoffset, elen, offset;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 97a0843bb..31fecbde2 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -42,12 +42,10 @@
* 12/20/98 find the free space bitmap (if it exists)
*/
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
#include "udfdecl.h"
+#include <linux/config.h>
+#include <linux/version.h>
#include <linux/blkdev.h>
#include <linux/malloc.h>
#include <linux/kernel.h>
@@ -65,6 +63,15 @@
#include <linux/init.h>
#include <asm/uaccess.h>
+#define VDS_POS_PRIMARY_VOL_DESC 0
+#define VDS_POS_UNALLOC_SPACE_DESC 1
+#define VDS_POS_LOGICAL_VOL_DESC 2
+#define VDS_POS_PARTITION_DESC 3
+#define VDS_POS_IMP_USE_VOL_DESC 4
+#define VDS_POS_VOL_DESC_PTR 5
+#define VDS_POS_TERMINATING_DESC 6
+#define VDS_POS_LENGTH 7
+
static char error_buf[1024];
/* These are the "meat" - everything else is stuffing */
@@ -1365,7 +1372,6 @@ udf_read_super(struct super_block *sb, void *options, int silent)
/* Fill in the rest of the superblock */
sb->s_op = &udf_sb_ops;
- sb->s_time = 0;
sb->dq_op = NULL;
sb->s_dirt = 0;
sb->s_magic = UDF_SUPER_MAGIC;
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 0e52198f5..63ebb5713 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -33,157 +33,93 @@
#include <linux/mm.h>
#include <linux/stat.h>
#include <linux/malloc.h>
+#include <linux/pagemap.h>
#include "udf_i.h"
-static int udf_readlink(struct dentry *, char *, int);
-static struct dentry * udf_follow_link(struct dentry * dentry,
- struct dentry * base, unsigned int follow);
-
-/*
- * symlinks can't do much...
- */
-struct inode_operations udf_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- udf_readlink, /* readlink */
- udf_follow_link,/* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
-};
-
-int udf_pc_to_char(char *from, int fromlen, char **to)
+static void udf_pc_to_char(char *from, int fromlen, char *to)
{
struct PathComponent *pc;
int elen = 0, len = 0;
+ char *p = to;
- *to = (char *)kmalloc(fromlen, GFP_KERNEL);
-
- if (!(*to))
- return -1;
-
- while (elen < fromlen)
- {
+ while (elen < fromlen) {
pc = (struct PathComponent *)(from + elen);
- if (pc->componentType == 1 && pc->lengthComponentIdent == 0)
- {
- (*to)[0] = '/';
- len = 1;
- }
- else if (pc->componentType == 3)
- {
- memcpy(&(*to)[len], "../", 3);
- len += 3;
- }
- else if (pc->componentType == 4)
- {
- memcpy(&(*to)[len], "./", 2);
- len += 2;
- }
- else if (pc->componentType == 5)
- {
- memcpy(&(*to)[len], pc->componentIdent, pc->lengthComponentIdent);
- len += pc->lengthComponentIdent + 1;
- (*to)[len-1] = '/';
+ switch (pc->componentType) {
+ case 1:
+ if (pc->lengthComponentIdent == 0) {
+ p = to;
+ *p++ = '/';
+ }
+ break;
+ case 3:
+ memcpy(p, "../", 3);
+ p += 3;
+ break;
+ case 4:
+ memcpy(p, "./", 2);
+ p += 2;
+ /* that would be . - just ignore */
+ break;
+ case 5:
+ memcpy(p+len, pc->componentIdent,
+ pc->lengthComponentIdent);
+ p += pc->lengthComponentIdent;
+ *p++ = '/';
}
elen += sizeof(struct PathComponent) + pc->lengthComponentIdent;
}
- if (len)
- {
- len --;
- (*to)[len] = '\0';
+ if (p>to+1) {
+ p[-1] = '\0';
}
- return len;
}
-static struct dentry * udf_follow_link(struct dentry * dentry,
- struct dentry * base, unsigned int follow)
+static int udf_symlink_filler(struct dentry * dentry, struct page *page)
{
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
- char *symlink, *tmpbuf;
- int len;
-
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
-
- if (!bh)
- return 0;
-
- symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
- }
- else
- {
- bh = bread(inode->i_dev, udf_block_map(inode, 0), inode->i_sb->s_blocksize);
-
- if (!bh)
- return 0;
-
- symlink = bh->b_data;
- }
-
- if ((len = udf_pc_to_char(symlink, inode->i_size, &tmpbuf)) >= 0)
- {
- base = lookup_dentry(tmpbuf, base, follow);
- kfree(tmpbuf);
- return base;
- }
- else
- return ERR_PTR(-ENOMEM);
-}
+ char *symlink;
+ int err;
-static int udf_readlink(struct dentry * dentry, char * buffer, int buflen)
-{
- struct inode *inode = dentry->d_inode;
- struct buffer_head *bh = NULL;
- char *symlink, *tmpbuf;
- int len;
+ char *p = (char*)kmap(page);
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- {
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+ err = -EIO;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ bh = udf_tread(inode->i_sb, inode->i_ino,
+ inode->i_sb->s_blocksize);
if (!bh)
- return 0;
+ goto out;
symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
- }
- else
- {
- bh = bread(inode->i_dev, udf_block_map(inode, 0), inode->i_sb->s_blocksize);
+ } else {
+ bh = bread(inode->i_dev, udf_block_map(inode, 0),
+ inode->i_sb->s_blocksize);
if (!bh)
- return 0;
+ goto out;
symlink = bh->b_data;
}
- if ((len = udf_pc_to_char(symlink, inode->i_size, &tmpbuf)) >= 0)
- {
- if (copy_to_user(buffer, tmpbuf, len > buflen ? buflen : len))
- len = -EFAULT;
- kfree(tmpbuf);
- }
- else
- len = -ENOMEM;
-
- UPDATE_ATIME(inode);
- if (bh)
- udf_release_data(bh);
- return len;
+ udf_pc_to_char(symlink, inode->i_size, p);
+ udf_release_data(bh);
+ SetPageUptodate(page);
+ kunmap(page);
+ UnlockPage(page);
+ return 0;
+out:
+ SetPageError(page);
+ kunmap(page);
+ UnlockPage(page);
+ return -EIO;
}
+
+/*
+ * symlinks can't do much...
+ */
+struct inode_operations udf_symlink_inode_operations = {
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ readpage: udf_symlink_filler,
+};
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index 676f8b3e6..1bf6e4cee 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -38,8 +38,7 @@ static void extent_trunc(struct inode * inode, lb_addr bloc, int *extoffset,
lb_addr neloc = { 0, 0 };
int nelen = 0;
int blocks = inode->i_sb->s_blocksize / 512;
- int last_block = (elen + inode->i_sb->s_blocksize - 1) / inode->i_sb->s_blocksize;
-
+ int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
if (offset)
{
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 407d6006d..310ba4aef 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -1,9 +1,6 @@
#ifndef __LINUX_UDF_SB_H
#define __LINUX_UDF_SB_H
-#include <linux/udf_167.h>
-#include <linux/udf_udf.h>
-
/* Since UDF 1.50 is ISO 13346 based... */
#define UDF_SUPER_MAGIC 0x15013346
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 543d15ea9..48dec10c5 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -1,9 +1,11 @@
#ifndef __UDF_DECL_H
#define __UDF_DECL_H
-#define UDF_VERSION_NOTICE "v0.8.9.3"
+#define UDF_VERSION_NOTICE "v0.8.9.4"
+#include <linux/udf_167.h>
#include <linux/udf_udf.h>
+#include "udfend.h"
#ifdef __KERNEL__
@@ -20,15 +22,33 @@
#endif
#include <linux/fs.h>
-/* if we're not defined, we must be compiling outside of the kernel tree */
+
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
-/* ... so override config */
#define CONFIG_UDF_FS_MODULE
-/* explicitly include udf_fs_sb.h and udf_fs_i.h */
#include <linux/udf_fs_sb.h>
#include <linux/udf_fs_i.h>
#endif
+#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
+#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
+
+#define CURRENT_UTIME (xtime.tv_usec)
+
+#define udf_file_entry_alloc_offset(inode)\
+ ((UDF_I_EXTENDED_FE(inode) ?\
+ sizeof(struct ExtendedFileEntry) :\
+ sizeof(struct FileEntry)) + UDF_I_LENEATTR(inode))
+
+#else
+
+#include <sys/types.h>
+
+#endif /* __KERNEL__ */
+
+
+
+#ifdef __KERNEL__
+
struct dentry;
struct inode;
struct task_struct;
@@ -48,8 +68,49 @@ struct udf_fileident_bh
int eoffset;
};
+#endif /* __KERNEL__ */
+
+struct udf_directory_record
+{
+ Uint32 d_parent;
+ Uint32 d_inode;
+ Uint32 d_name[255];
+};
+
+
+struct udf_vds_record
+{
+ Uint32 block;
+ Uint32 volDescSeqNum;
+};
+
+struct ktm
+{
+ int tm_sec;
+ int tm_min;
+ int tm_hour;
+ int tm_mday;
+ int tm_mon;
+ int tm_year;
+ int tm_isdst;
+};
+
+struct ustr
+{
+ Uint8 u_cmpID;
+ Uint8 u_name[UDF_NAME_LEN-1];
+ Uint8 u_len;
+ Uint8 padding;
+ unsigned long u_hash;
+};
+
+#ifdef __KERNEL__
+
+/* super.c */
extern void udf_error(struct super_block *, const char *, const char *, ...);
extern void udf_warning(struct super_block *, const char *, const char *, ...);
+
+/* namei.c */
extern int udf_write_fi(struct FileIdentDesc *, struct FileIdentDesc *, struct udf_fileident_bh *, Uint8 *, Uint8 *);
extern struct dentry * udf_lookup(struct inode *, struct dentry *);
extern int udf_create(struct inode *, struct dentry *, int);
@@ -60,7 +121,11 @@ extern int udf_unlink(struct inode *, struct dentry *);
extern int udf_symlink(struct inode *, struct dentry *, const char *);
extern int udf_link(struct dentry *, struct inode *, struct dentry *);
extern int udf_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+
+/* file.c */
extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+
+/* inode.c */
extern struct inode *udf_iget(struct super_block *, lb_addr);
extern int udf_sync_inode(struct inode *);
extern struct buffer_head * udf_expand_adinicb(struct inode *, int *, int, int *);
@@ -80,9 +145,10 @@ extern int udf_insert_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct
extern int udf_delete_aext(struct inode *, lb_addr, int, lb_addr, Uint32, struct buffer_head *);
extern int udf_next_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
extern int udf_current_aext(struct inode *, lb_addr *, int *, lb_addr *, Uint32 *, struct buffer_head **, int);
+extern void udf_discard_prealloc(struct inode *);
+/* misc.c */
extern int udf_read_tagged_data(char *, int size, int fd, int block, int partref);
-
extern struct buffer_head *udf_tread(struct super_block *, int, int);
extern struct GenericAttrFormat *udf_add_extendedattr(struct inode *, Uint32, Uint32, Uint8, struct buffer_head **);
extern struct GenericAttrFormat *udf_get_extendedattr(struct inode *, Uint32, Uint8, struct buffer_head **);
@@ -91,186 +157,73 @@ extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, Uint3
extern struct buffer_head *udf_read_untagged(struct super_block *, Uint32, Uint32);
extern void udf_release_data(struct buffer_head *);
+/* lowlevel.c */
extern unsigned int udf_get_last_session(kdev_t);
extern unsigned int udf_get_last_block(kdev_t, int *);
+/* partition.c */
extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
extern Uint32 udf_get_lb_pblock(struct super_block *, lb_addr, Uint32);
+/* unicode.c */
extern int udf_get_filename(Uint8 *, Uint8 *, int);
+/* ialloc.c */
extern void udf_free_inode(struct inode *);
extern struct inode * udf_new_inode (const struct inode *, int, int *);
-extern void udf_discard_prealloc(struct inode *);
+
+/* truncate.c */
extern void udf_truncate(struct inode *);
extern void udf_truncate_adinicb(struct inode *);
+
+/* balloc.c */
extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
extern int udf_new_block(const struct inode *, Uint16, Uint32, int *);
extern int udf_sync_file(struct file *, struct dentry *);
-#else
-
-#include <sys/types.h>
+/* directory.c */
+extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *, struct buffer_head **, int *);
+extern struct FileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
#endif /* __KERNEL__ */
-#include "udfend.h"
-
-/* structures */
-struct udf_directory_record
-{
- Uint32 d_parent;
- Uint32 d_inode;
- Uint32 d_name[255];
-};
-
-#define VDS_POS_PRIMARY_VOL_DESC 0
-#define VDS_POS_UNALLOC_SPACE_DESC 1
-#define VDS_POS_LOGICAL_VOL_DESC 2
-#define VDS_POS_PARTITION_DESC 3
-#define VDS_POS_IMP_USE_VOL_DESC 4
-#define VDS_POS_VOL_DESC_PTR 5
-#define VDS_POS_TERMINATING_DESC 6
-#define VDS_POS_LENGTH 7
-
-struct udf_vds_record
-{
- Uint32 block;
- Uint32 volDescSeqNum;
-};
-
-struct ktm
-{
- int tm_sec;
- int tm_min;
- int tm_hour;
- int tm_mday;
- int tm_mon;
- int tm_year;
- int tm_isdst;
-};
-
-struct ustr
-{
- Uint8 u_cmpID;
- Uint8 u_name[UDF_NAME_LEN-1];
- Uint8 u_len;
- Uint8 padding;
- unsigned long u_hash;
-};
-
-
-#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
-#define udf_variable_to_fixed(x) ( ( ( (x) / 39 ) << 5 ) + ( (x) % 39 ) )
-
-#ifdef __KERNEL__
-
-#define CURRENT_UTIME (xtime.tv_usec)
-
-#define udf_file_entry_alloc_offset(inode)\
- ((UDF_I_EXTENDED_FE(inode) ?\
- sizeof(struct ExtendedFileEntry) :\
- sizeof(struct FileEntry)) + UDF_I_LENEATTR(inode))
-
-#define udf_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
-#define udf_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define udf_test_bit(nr, addr) ext2_test_bit(nr, addr)
-#define udf_find_first_one_bit(addr, size) find_first_one_bit(addr, size)
-#define udf_find_next_one_bit(addr, size, offset) find_next_one_bit(addr, size, offset)
-
-#define leBPL_to_cpup(x) leNUM_to_cpup(BITS_PER_LONG, x)
-#define leNUM_to_cpup(x,y) xleNUM_to_cpup(x,y)
-#define xleNUM_to_cpup(x,y) (le ## x ## _to_cpup(y))
-
-extern inline int find_next_one_bit (void * addr, int size, int offset)
-{
- unsigned long * p = ((unsigned long *) addr) + (offset / BITS_PER_LONG);
- unsigned long result = offset & ~(BITS_PER_LONG-1);
- unsigned long tmp;
-
- if (offset >= size)
- return size;
- size -= result;
- offset &= (BITS_PER_LONG-1);
- if (offset)
- {
- tmp = leBPL_to_cpup(p++);
- tmp &= ~0UL << offset;
- if (size < BITS_PER_LONG)
- goto found_first;
- if (tmp)
- goto found_middle;
- size -= BITS_PER_LONG;
- result += BITS_PER_LONG;
- }
- while (size & ~(BITS_PER_LONG-1))
- {
- if ((tmp = leBPL_to_cpup(p++)))
- goto found_middle;
- result += BITS_PER_LONG;
- size -= BITS_PER_LONG;
- }
- if (!size)
- return result;
- tmp = leBPL_to_cpup(p);
-found_first:
- tmp &= ~0UL >> (BITS_PER_LONG-size);
-found_middle:
- return result + ffz(~tmp);
-}
-
-#define find_first_one_bit(addr, size)\
- find_next_one_bit((addr), (size), 0)
-
-#endif
-
/* Miscellaneous UDF Prototypes */
+/* unicode.c */
extern int udf_ustr_to_dchars(Uint8 *, const struct ustr *, int);
extern int udf_ustr_to_char(Uint8 *, const struct ustr *, int);
extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
extern int udf_dchars_to_ustr(struct ustr *, const Uint8 *, int);
extern int udf_char_to_ustr(struct ustr *, const Uint8 *, int);
extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
-
-extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
extern int udf_translate_to_linux(Uint8 *, Uint8 *, int, Uint8 *, int);
extern int udf_build_ustr(struct ustr *, dstring *, int);
extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
+/* crc.c */
+extern Uint16 udf_crc(Uint8 *, Uint32, Uint16);
+
+/* misc.c */
extern uid_t udf_convert_uid(int);
extern gid_t udf_convert_gid(int);
extern Uint32 udf64_low32(Uint64);
extern Uint32 udf64_high32(Uint64);
+extern void udf_update_tag(char *, int);
+extern void udf_new_tag(char *, Uint16, Uint16, Uint16, Uint32, int);
-
+/* udftime.c */
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
extern time_t udf_converttime (struct ktm *);
-#ifdef __KERNEL__
-extern Uint8 *
-udf_filead_read(struct inode *, Uint8 *, Uint8, lb_addr, int *, int *,
- struct buffer_head **, int *);
-
-extern struct FileIdentDesc *
-udf_fileident_read(struct inode *, int *,
- struct udf_fileident_bh *,
- struct FileIdentDesc *,
- lb_addr *, Uint32 *,
- Uint32 *, struct buffer_head **);
-#endif
-extern struct FileIdentDesc *
-udf_get_fileident(void * buffer, int bufsize, int * offset);
+/* directory.c */
+extern struct FileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
extern Uint8 * udf_get_filead(struct FileEntry *, Uint8 *, int, int, int, int *);
-extern void udf_update_tag(char *, int);
-extern void udf_new_tag(char *, Uint16, Uint16, Uint16, Uint32, int);
-
-#endif
+#endif /* __UDF_DECL_H */
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h
index 031f5b507..67161d7ae 100644
--- a/fs/udf/udfend.h
+++ b/fs/udf/udfend.h
@@ -3,6 +3,8 @@
#ifndef __KERNEL__
+#include <sys/types.h>
+
#if __BYTE_ORDER == 0
#error "__BYTE_ORDER must be defined"
@@ -44,8 +46,11 @@
#endif /* __BYTE_ORDER == 0 */
+#include <string.h>
+
#else /* __KERNEL__ */
+#include <asm/byteorder.h>
#include <linux/string.h>
#endif /* ! __KERNEL__ */
diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c
index 0b23ad37f..f2be33cfa 100644
--- a/fs/ufs/dir.c
+++ b/fs/ufs/dir.c
@@ -210,9 +210,7 @@ struct inode_operations ufs_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
ufs_permission, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/ufs/file.c b/fs/ufs/file.c
index 33d68ba5d..b014e6c14 100644
--- a/fs/ufs/file.c
+++ b/fs/ufs/file.c
@@ -153,9 +153,7 @@ struct inode_operations ufs_file_inode_operations = {
ufs_getfrag_block, /* get_block */
block_read_full_page, /* readpage */
block_write_full_page, /* writepage */
- block_flushpage, /* flushpage */
ufs_truncate, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};
diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c
index afcdcd600..21171a864 100644
--- a/fs/ufs/inode.c
+++ b/fs/ufs/inode.c
@@ -631,7 +631,9 @@ void ufs_read_inode (struct inode * inode)
else if (S_ISDIR(inode->i_mode))
inode->i_op = &ufs_dir_inode_operations;
else if (S_ISLNK(inode->i_mode))
- inode->i_op = &ufs_symlink_inode_operations;
+ inode->i_op = inode->i_blocks
+ ?&ufs_symlink_inode_operations
+ :&ufs_fast_symlink_inode_operations;
else
init_special_inode(inode, inode->i_mode,
SWAB32(ufs_inode->ui_u2.ui_addr.ui_db[0]));
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 278f8826a..497f69867 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -751,55 +751,42 @@ end_unlink:
int ufs_symlink (struct inode * dir, struct dentry * dentry,
const char * symname)
{
- struct super_block * sb;
+ struct super_block * sb = dir->i_sb;
struct ufs_dir_entry * de;
struct inode * inode;
- struct buffer_head * bh, * name_block;
- char * link;
- unsigned i, l;
+ struct buffer_head * bh = NULL;
+ unsigned l;
int err;
- char c;
- unsigned swab;
+ unsigned swab = sb->u.ufs_sb.s_swab;
UFSD(("ENTER\n"))
- sb = dir->i_sb;
- swab = sb->u.ufs_sb.s_swab;
- bh = name_block = NULL;
+
+ err = -ENAMETOOLONG;
+ l = strlen(symname)+1;
+ if (l > dir->i_sb->s_blocksize)
+ goto out;
+
err = -EIO;
if (!(inode = ufs_new_inode (dir, S_IFLNK, &err))) {
return err;
}
inode->i_mode = S_IFLNK | S_IRWXUGO;
- inode->i_op = &ufs_symlink_inode_operations;
- for (l = 0; l < sb->s_blocksize - 1 && symname [l]; l++);
- /***if (l >= sizeof (inode->u.ufs_i.i_data)) {***/
+ /***if (l > sizeof (inode->u.ufs_i.i_data)) {***/
if (1) {
/* slow symlink */
- name_block = ufs_bread (inode, 0, 1, &err);
- if (!name_block) {
- inode->i_nlink--;
- mark_inode_dirty(inode);
- iput (inode);
- return err;
- }
- link = name_block->b_data;
-
+ inode->i_op = &ufs_symlink_inode_operations;
+ err = block_symlink(inode, symname, l);
+ if (err)
+ goto out_no_entry;
} else {
/* fast symlink */
- link = (char *) inode->u.ufs_i.i_u1.i_data;
- }
- i = 0;
- while (i < sb->s_blocksize - 1 && (c = *(symname++)))
- link[i++] = c;
- link[i] = 0;
- if (name_block) {
- mark_buffer_dirty(name_block, 1);
- brelse (name_block);
+ inode->i_op = &ufs_fast_symlink_inode_operations;
+ memcpy((char*)&inode->u.ufs_i.i_u1.i_data,symname,l);
+ inode->i_size = l-1;
}
- inode->i_size = i;
mark_inode_dirty(inode);
bh = ufs_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
@@ -828,16 +815,12 @@ out_no_entry:
int ufs_link (struct dentry * old_dentry, struct inode * dir,
struct dentry *dentry)
{
- struct super_block * sb;
struct inode *inode = old_dentry->d_inode;
+ struct super_block * sb = inode->i_sb;
struct ufs_dir_entry * de;
struct buffer_head * bh;
int err;
- unsigned swab;
-
- inode = old_dentry->d_inode;
- sb = inode->i_sb;
- swab = sb->u.ufs_sb.s_swab;
+ unsigned swab = sb->u.ufs_sb.s_swab;
if (S_ISDIR(inode->i_mode))
return -EPERM;
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
index 3df5c40a6..06ee82740 100644
--- a/fs/ufs/symlink.c
+++ b/fs/ufs/symlink.c
@@ -23,118 +23,29 @@
* ext2 symlink handling code
*/
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/ufs_fs.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
-
-
-#undef UFS_SYMLINK_DEBUG
-#ifdef UFS_SYMLINK_DEBUG
-#define UFSD(x) printk("(%s, %d), %s:", __FILE__, __LINE__, __FUNCTION__); printk x;
-#else
-#define UFSD(x)
-#endif
-
-
-static struct dentry * ufs_follow_link(struct dentry * dentry,
- struct dentry * base, unsigned int follow)
+static int ufs_readlink(struct dentry *dentry, char *buffer, int buflen)
{
- struct inode * inode;
- struct buffer_head * bh;
- int error;
- char * link;
-
- UFSD(("ENTER\n"))
-
- inode = dentry->d_inode;
- bh = NULL;
- /* slow symlink */
- if (inode->i_blocks) {
- if (!(bh = ufs_bread (inode, 0, 0, &error))) {
- dput(base);
- return ERR_PTR(-EIO);
- }
- link = bh->b_data;
- }
- /* fast symlink */
- else {
- link = (char *) inode->u.ufs_i.i_u1.i_symlink;
- }
- UPDATE_ATIME(inode);
- base = lookup_dentry(link, base, follow);
- if (bh)
- brelse(bh);
- UFSD(("EXIT\n"))
- return base;
+ char *s = (char *)dentry->d_inode->u.ufs_i.i_u1.i_symlink;
+ return vfs_readlink(dentry, buffer, buflen, s);
}
-static int ufs_readlink (struct dentry * dentry, char * buffer, int buflen)
+static struct dentry *ufs_follow_link(struct dentry *dentry, struct dentry *base, unsigned flags)
{
- struct super_block * sb;
- struct inode * inode;
- struct buffer_head * bh;
- char * link;
- int i;
-
- UFSD(("ENTER\n"))
-
- inode = dentry->d_inode;
- sb = inode->i_sb;
- bh = NULL;
- if (buflen > sb->s_blocksize - 1)
- buflen = sb->s_blocksize - 1;
- /* slow symlink */
- if (inode->i_blocks) {
- int err;
- bh = ufs_bread (inode, 0, 0, &err);
- if (!bh) {
- if(err < 0) /* indicate type of error */
- return err;
- return 0;
- }
- link = bh->b_data;
- }
- /* fast symlink */
- else {
- link = (char *) inode->u.ufs_i.i_u1.i_symlink;
- }
- i = 0;
- while (i < buflen && link[i])
- i++;
- if (copy_to_user(buffer, link, i))
- i = -EFAULT;
- UPDATE_ATIME(inode);
- if (bh)
- brelse (bh);
- UFSD(("ENTER\n"))
- return i;
+ char *s = (char *)dentry->d_inode->u.ufs_i.i_u1.i_symlink;
+ return vfs_follow_link(dentry, base, flags, s);
}
+struct inode_operations ufs_fast_symlink_inode_operations = {
+ readlink: ufs_readlink,
+ follow_link: ufs_follow_link,
+};
+
struct inode_operations ufs_symlink_inode_operations = {
- NULL, /* no file-operations */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- ufs_readlink, /* readlink */
- ufs_follow_link, /* follow_link */
- NULL, /* get_block */
- NULL, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: ufs_getfrag_block,
+ readpage: block_read_full_page
};
diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c
index 2d33bd3c9..57de81eb8 100644
--- a/fs/ufs/truncate.c
+++ b/fs/ufs/truncate.c
@@ -63,7 +63,7 @@
#define DIRECT_FRAGMENT ((inode->i_size + uspi->s_fsize - 1) >> uspi->s_fshift)
#define DATA_BUFFER_USED(bh) \
- (atomic_read(&bh->b_count) || buffer_locked(bh))
+ (atomic_read(&bh->b_count)>1 || buffer_locked(bh))
static int ufs_trunc_direct (struct inode * inode)
{
diff --git a/fs/umsdos/README-WIP.txt b/fs/umsdos/README-WIP.txt
index f53426a13..9c09891de 100644
--- a/fs/umsdos/README-WIP.txt
+++ b/fs/umsdos/README-WIP.txt
@@ -11,6 +11,16 @@ I'd call it pre-release, and ask for as many people as possible to
come and test it! See notes below for some more information, or if
you are trying to use UMSDOS as root partition.
+Userland NOTE: new umsdos_progs (umssync, umssetup, udosctl & friends) that
+will compile and work on 2.2.x kernels and glibc based systems may be found
+at http://cvs.linux.hr/
+
+Also look at the quick-hack "homepage" for umsdos filesystem at
+http://www.voyager.hr/~mnalis/umsdos
+
+Information below is getting outdated slowly -- I'll fix it one day when I
+get enough time - there are more important things to fix right now.
+
Legend: those lines marked with '+' on the beggining of line indicates it
passed all of my tests, and performed perfect in all of them.
diff --git a/fs/umsdos/check.c b/fs/umsdos/check.c
index 1eda3df93..6eebff74a 100644
--- a/fs/umsdos/check.c
+++ b/fs/umsdos/check.c
@@ -60,6 +60,14 @@ void check_page_tables (void)
#if UMS_DEBUG
/*
+ * check for wait queue in 2.3.x
+ */
+inline void uq_log (char *txt, struct inode *inode)
+{
+ printk (KERN_ERR "%s: (%lu) magic=%lu creator=%lu lock=%u\n", txt, inode->i_ino, inode->u.umsdos_i.dir_info.p.__magic, inode->u.umsdos_i.dir_info.p.__creator, inode->u.umsdos_i.dir_info.p.lock.lock);
+}
+
+/*
* check a superblock
*/
@@ -213,6 +221,7 @@ void check_dentry_path (struct dentry *dentry, const char *desc)
}
}
#else
+inline void uq_log (char *txt, struct inode *inode) {};
void check_sb (struct super_block *sb, const char c) {};
void check_inode (struct inode *inode) {};
void checkd_inode (struct inode *inode) {};
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c
index c09c293cf..af875aa79 100644
--- a/fs/umsdos/dir.c
+++ b/fs/umsdos/dir.c
@@ -49,9 +49,7 @@ struct dentry_operations umsdos_dentry_operations =
umsdos_dentry_validate, /* d_revalidate(struct dentry *, int) */
NULL, /* d_hash */
NULL, /* d_compare */
- umsdos_dentry_dput, /* d_delete(struct dentry *) */
- NULL,
- NULL,
+ umsdos_dentry_dput /* d_delete(struct dentry *) */
};
@@ -834,9 +832,7 @@ struct inode_operations umsdos_dir_inode_operations =
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
- NULL, /* revalidate */
+ NULL /* revalidate */
};
diff --git a/fs/umsdos/inode.c b/fs/umsdos/inode.c
index 171aa15dc..252f8a48b 100644
--- a/fs/umsdos/inode.c
+++ b/fs/umsdos/inode.c
@@ -94,6 +94,11 @@ void umsdos_setup_dir(struct dentry *dir)
printk(KERN_ERR "umsdos_setup_dir: %s/%s not a dir!\n",
dir->d_parent->d_name.name, dir->d_name.name);
+ init_waitqueue_head (&inode->u.umsdos_i.dir_info.p);
+ inode->u.umsdos_i.dir_info.looking = 0;
+ inode->u.umsdos_i.dir_info.creating = 0;
+ inode->u.umsdos_i.dir_info.pid = 0;
+
inode->i_op = &umsdos_rdir_inode_operations;
if (umsdos_have_emd(dir)) {
Printk((KERN_DEBUG "umsdos_setup_dir: %s/%s using EMD\n",
@@ -311,7 +316,7 @@ static struct super_operations umsdos_sops =
NULL, /* write_super */
fat_statfs, /* statfs */
NULL, /* remount_fs */
- fat_clear_inode, /* clear_inode */
+ fat_clear_inode /* clear_inode */
};
/*
@@ -333,7 +338,7 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
if (!res)
goto out_fail;
- printk (KERN_INFO "UMSDOS 0.85 "
+ printk (KERN_INFO "UMSDOS 0.86 "
"(compatibility level %d.%d, fast msdos)\n",
UMSDOS_VERSION, UMSDOS_RELEASE);
diff --git a/fs/umsdos/ioctl.c b/fs/umsdos/ioctl.c
index f26d19ba8..239043318 100644
--- a/fs/umsdos/ioctl.c
+++ b/fs/umsdos/ioctl.c
@@ -217,14 +217,11 @@ dentry->d_parent->d_name.name, dentry->d_name.name, cmd, data_ptr));
*
* Return 0 if success.
*/
- extern struct inode_operations umsdos_rdir_inode_operations;
ret = umsdos_make_emd(dentry);
Printk(("UMSDOS_ioctl_dir: INIT_EMD %s/%s, ret=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, ret));
- dir->i_op = (ret == 0)
- ? &umsdos_dir_inode_operations
- : &umsdos_rdir_inode_operations;
+ umsdos_setup_dir (dentry);
goto out;
}
@@ -280,6 +277,8 @@ printk("umsdos_ioctl: renaming %s/%s to %s/%s\n",
old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
ret = msdos_rename (dir, old_dentry, dir, new_dentry);
+ d_drop(new_dentry);
+ d_drop(old_dentry);
dput(new_dentry);
}
dput(old_dentry);
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
index 444e9ffae..415f5e3fb 100644
--- a/fs/umsdos/namei.c
+++ b/fs/umsdos/namei.c
@@ -22,7 +22,20 @@
#include <linux/umsdos_fs.h>
#include <linux/malloc.h>
-#if 1
+#define UMSDOS_DIR_LOCK
+
+#ifdef UMSDOS_DIR_LOCK
+
+static inline void u_sleep_on (struct inode *dir)
+{
+ sleep_on (&dir->u.umsdos_i.dir_info.p);
+}
+
+static inline void u_wake_up (struct inode *dir)
+{
+ wake_up (&dir->u.umsdos_i.dir_info.p);
+}
+
/*
* Wait for creation exclusivity.
* Return 0 if the dir was already available.
@@ -34,9 +47,10 @@ static int umsdos_waitcreate (struct inode *dir)
{
int ret = 0;
- if (dir->u.umsdos_i.u.dir_info.creating
- && dir->u.umsdos_i.u.dir_info.pid != current->pid) {
- sleep_on (&dir->u.umsdos_i.u.dir_info.p);
+ if (dir->u.umsdos_i.dir_info.creating
+ && dir->u.umsdos_i.dir_info.pid != current->pid) {
+ PRINTK (("creating && dir_info.pid=%lu, current->pid=%u\n", dir->u.umsdos_i.dir_info.pid, current->pid));
+ u_sleep_on (dir);
ret = 1;
}
return ret;
@@ -47,8 +61,8 @@ static int umsdos_waitcreate (struct inode *dir)
*/
static void umsdos_waitlookup (struct inode *dir)
{
- while (dir->u.umsdos_i.u.dir_info.looking) {
- sleep_on (&dir->u.umsdos_i.u.dir_info.p);
+ while (dir->u.umsdos_i.dir_info.looking) {
+ u_sleep_on (dir);
}
}
@@ -90,8 +104,8 @@ void umsdos_lockcreate (struct inode *dir)
* if we (the process) own the lock
*/
while (umsdos_waitcreate (dir) != 0);
- dir->u.umsdos_i.u.dir_info.creating++;
- dir->u.umsdos_i.u.dir_info.pid = current->pid;
+ dir->u.umsdos_i.dir_info.creating++;
+ dir->u.umsdos_i.dir_info.pid = current->pid;
umsdos_waitlookup (dir);
}
@@ -110,10 +124,10 @@ static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
if (umsdos_waitcreate (dir1) == 0
&& umsdos_waitcreate (dir2) == 0) {
/* We own both now */
- dir1->u.umsdos_i.u.dir_info.creating++;
- dir1->u.umsdos_i.u.dir_info.pid = current->pid;
- dir2->u.umsdos_i.u.dir_info.creating++;
- dir2->u.umsdos_i.u.dir_info.pid = current->pid;
+ dir1->u.umsdos_i.dir_info.creating++;
+ dir1->u.umsdos_i.dir_info.pid = current->pid;
+ dir2->u.umsdos_i.dir_info.creating++;
+ dir2->u.umsdos_i.dir_info.pid = current->pid;
break;
}
}
@@ -127,7 +141,7 @@ static void umsdos_lockcreate2 (struct inode *dir1, struct inode *dir2)
void umsdos_startlookup (struct inode *dir)
{
while (umsdos_waitcreate (dir) != 0);
- dir->u.umsdos_i.u.dir_info.looking++;
+ dir->u.umsdos_i.dir_info.looking++;
}
/*
@@ -135,12 +149,12 @@ void umsdos_startlookup (struct inode *dir)
*/
void umsdos_unlockcreate (struct inode *dir)
{
- dir->u.umsdos_i.u.dir_info.creating--;
- if (dir->u.umsdos_i.u.dir_info.creating < 0) {
- printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.creating < 0: %d"
- ,dir->u.umsdos_i.u.dir_info.creating);
+ dir->u.umsdos_i.dir_info.creating--;
+ if (dir->u.umsdos_i.dir_info.creating < 0) {
+ printk ("UMSDOS: dir->u.umsdos_i.dir_info.creating < 0: %d"
+ ,dir->u.umsdos_i.dir_info.creating);
}
- wake_up (&dir->u.umsdos_i.u.dir_info.p);
+ u_wake_up (dir);
}
/*
@@ -148,12 +162,12 @@ void umsdos_unlockcreate (struct inode *dir)
*/
void umsdos_endlookup (struct inode *dir)
{
- dir->u.umsdos_i.u.dir_info.looking--;
- if (dir->u.umsdos_i.u.dir_info.looking < 0) {
- printk ("UMSDOS: dir->u.umsdos_i.u.dir_info.looking < 0: %d"
- ,dir->u.umsdos_i.u.dir_info.looking);
+ dir->u.umsdos_i.dir_info.looking--;
+ if (dir->u.umsdos_i.dir_info.looking < 0) {
+ printk ("UMSDOS: dir->u.umsdos_i.dir_info.looking < 0: %d"
+ ,dir->u.umsdos_i.dir_info.looking);
}
- wake_up (&dir->u.umsdos_i.u.dir_info.p);
+ u_wake_up (dir);
}
#else
@@ -475,8 +489,6 @@ out:
* Let's go for simplicity...
*/
-extern struct inode_operations umsdos_symlink_inode_operations;
-
/*
* AV. Should be called with dir->i_sem down.
*/
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
index c7bb8fb1b..2b972a524 100644
--- a/fs/umsdos/rdir.c
+++ b/fs/umsdos/rdir.c
@@ -252,6 +252,5 @@ struct inode_operations umsdos_rdir_inode_operations =
NULL, /* get_block */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
- NULL, /* revalidate */
+ NULL /* revalidate */
};
diff --git a/fs/umsdos/symlink.c b/fs/umsdos/symlink.c
index 8f94230e3..7bcd09e44 100644
--- a/fs/umsdos/symlink.c
+++ b/fs/umsdos/symlink.c
@@ -5,143 +5,18 @@
* inspired from linux/fs/msdos/file.c Werner Almesberger
*
* Extended MS-DOS regular file handling primitives
+ *
+ * Wow. It looks like we could support them on FAT with little (if any)
+ * problems. Oh, well...
*/
-#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/msdos_fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/stat.h>
-#include <linux/umsdos_fs.h>
-#include <linux/malloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static struct file_operations umsdos_symlink_operations;
-
-
-/*
- * Read the data associate with the symlink.
- * Return length read in buffer or a negative error code.
- *
- */
-
-int umsdos_readlink_x ( struct dentry *dentry,
- char *buffer,
- int bufsiz)
-{
- size_t size = dentry->d_inode->i_size;
- loff_t loffs = 0;
- ssize_t ret;
- struct file filp;
-
-Printk((KERN_DEBUG "UMSDOS_read: %s/%s, size=%u\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, size));
-
- fill_new_filp (&filp, dentry);
- filp.f_reada = 0;
- filp.f_flags = O_RDONLY;
- filp.f_op = &umsdos_symlink_operations;
-
- if (size > bufsiz)
- size = bufsiz;
-
- ret = fat_file_read (&filp, buffer, size, &loffs);
- if (ret != size) {
- ret = -EIO;
- }
- return ret;
-}
-
-
-
-static int UMSDOS_readlink (struct dentry *dentry, char *buffer, int buflen)
-{
- return umsdos_readlink_x (dentry, buffer, buflen);
-}
-
-/* this one mostly stolen from romfs :) */
-static struct dentry *UMSDOS_followlink (struct dentry *dentry,
- struct dentry *base,
- unsigned int follow)
-{
- struct inode *inode = dentry->d_inode;
- char *symname;
- int len, cnt;
- mm_segment_t old_fs = get_fs ();
-
-Printk((KERN_DEBUG "UMSDOS_followlink /mn/: (%s/%s)\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
-
- len = inode->i_size;
-
- if (!(symname = kmalloc (len + 1, GFP_KERNEL))) {
- dentry = ERR_PTR (-ENOMEM);
- goto outnobuf;
- }
-
- set_fs (KERNEL_DS); /* we read into kernel space this time */
- cnt = umsdos_readlink_x (dentry, symname, len);
- set_fs (old_fs);
-
- if (len != cnt) {
- dentry = ERR_PTR (-EIO);
- goto out;
- }
-
- symname[len] = 0;
- dentry = lookup_dentry (symname, base, follow);
- kfree (symname);
-
- if (0) {
- out:
- kfree (symname);
- outnobuf:
- dput (base);
- }
- return dentry;
-}
-
-/* needed to patch the file structure */
-static struct file_operations umsdos_symlink_operations =
-{
- NULL, /* lseek - default */
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir - bad */
- NULL, /* poll - default */
- NULL, /* ioctl - default */
- NULL, /* mmap */
- NULL, /* no special open is needed */
- NULL, /* no flush code */
- NULL, /* release */
- NULL /* fsync */
-};
-
struct inode_operations umsdos_symlink_inode_operations =
{
- NULL, /* default file operations (none) */
- NULL, /* create */
- NULL, /* lookup */
- NULL, /* link */
- NULL, /* unlink */
- NULL, /* symlink */
- NULL, /* mkdir */
- NULL, /* rmdir */
- NULL, /* mknod */
- NULL, /* rename */
- UMSDOS_readlink, /* readlink */
- UMSDOS_followlink, /* followlink */
- fat_get_block, /* get_block */
- block_read_full_page, /* readpage */
- NULL, /* writepage */
- NULL, /* flushpage */
- NULL, /* truncate */
- NULL, /* permission */
- NULL, /* smap */
- NULL /* revalidate */
+ readlink: page_readlink,
+ follow_link: page_follow_link,
+ get_block: fat_get_block,
+ readpage: block_read_full_page
};
-
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 0f23487ba..2ee7aaf0a 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -1205,10 +1205,8 @@ struct inode_operations vfat_dir_inode_operations = {
NULL, /* get_block */
NULL, /* readpage */
NULL, /* writepage */
- NULL, /* flushpage */
NULL, /* truncate */
NULL, /* permission */
- NULL, /* smap */
NULL /* revalidate */
};