From 25ee7e3832951cf5896b194f6cd929a44863f419 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 25 Apr 2005 08:18:14 -0700 Subject: [PATCH] fs/aio.c: make some code static This patch makes some needlessly global code static. Signed-off-by: Adrian Bunk Acked-by: Benjamin LaHaise Signed-off-by: Linus Torvalds --- fs/aio.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index d06a266769bc..a82214d2e46d 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -40,8 +40,8 @@ #define dprintk(x...) do { ; } while (0) #endif -long aio_run = 0; /* for testing only */ -long aio_wakeups = 0; /* for testing only */ +static long aio_run = 0; /* for testing only */ +static long aio_wakeups = 0; /* for testing only */ /*------ sysctl variables----*/ atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ @@ -58,7 +58,7 @@ static void aio_fput_routine(void *); static DECLARE_WORK(fput_work, aio_fput_routine, NULL); static DEFINE_SPINLOCK(fput_lock); -LIST_HEAD(fput_head); +static LIST_HEAD(fput_head); static void aio_kick_handler(void *); @@ -290,7 +290,7 @@ static void aio_cancel_all(struct kioctx *ctx) spin_unlock_irq(&ctx->ctx_lock); } -void wait_for_all_aios(struct kioctx *ctx) +static void wait_for_all_aios(struct kioctx *ctx) { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); @@ -592,7 +592,7 @@ static void use_mm(struct mm_struct *mm) * Comments: Called with ctx->ctx_lock held. This nests * task_lock instead ctx_lock. */ -void unuse_mm(struct mm_struct *mm) +static void unuse_mm(struct mm_struct *mm) { struct task_struct *tsk = current; @@ -879,7 +879,7 @@ static void aio_kick_handler(void *data) * and if required activate the aio work queue to process * it */ -void queue_kicked_iocb(struct kiocb *iocb) +static void queue_kicked_iocb(struct kiocb *iocb) { struct kioctx *ctx = iocb->ki_ctx; unsigned long flags; @@ -1401,7 +1401,7 @@ static ssize_t aio_fsync(struct kiocb *iocb) * Performs the initial checks and aio retry method * setup for the kiocb at the time of io submission. */ -ssize_t aio_setup_iocb(struct kiocb *kiocb) +static ssize_t aio_setup_iocb(struct kiocb *kiocb) { struct file *file = kiocb->ki_filp; ssize_t ret = 0; @@ -1470,7 +1470,8 @@ ssize_t aio_setup_iocb(struct kiocb *kiocb) * because this callback isn't used for wait queues which * are nested inside ioctx lock (i.e. ctx->wait) */ -int aio_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) +static int aio_wake_function(wait_queue_t *wait, unsigned mode, + int sync, void *key) { struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait); @@ -1620,7 +1621,8 @@ asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr, * Finds a given iocb for cancellation. * MUST be called with ctx->ctx_lock held. */ -struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, u32 key) +static struct kiocb *lookup_kiocb(struct kioctx *ctx, struct iocb __user *iocb, + u32 key) { struct list_head *pos; /* TODO: use a hash or array, this sucks. */ -- cgit v1.2.3 From 94f2f715771d0aa5554451d1e2a920f11b8be3fe Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 25 Apr 2005 18:32:12 -0700 Subject: [PATCH] isofs includes sanitized fs/isofs includes trimmed down to something resembling sanity. Kernel-only parts of linux/iso_fs.h and entire linux/iso_fs_{sb,i}.h moved to fs/isofs/isofs.h. A lot of useless #include in fs/isofs/*.c killed. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/isofs/compress.c | 21 +---- fs/isofs/dir.c | 13 +--- fs/isofs/export.c | 6 +- fs/isofs/inode.c | 19 +---- fs/isofs/isofs.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++ fs/isofs/joliet.c | 6 +- fs/isofs/namei.c | 13 +--- fs/isofs/rock.c | 8 +- fs/isofs/util.c | 5 +- include/linux/iso_fs.h | 147 ----------------------------------- include/linux/iso_fs_i.h | 27 ------- include/linux/iso_fs_sb.h | 34 --------- 12 files changed, 203 insertions(+), 286 deletions(-) create mode 100644 fs/isofs/isofs.h delete mode 100644 include/linux/iso_fs_i.h delete mode 100644 include/linux/iso_fs_sb.h (limited to 'fs') diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index fb42c3f3bf0d..34a44e451689 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -18,29 +18,12 @@ #include #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include + #include #include -#include - -#include -#include -#include +#include "isofs.h" #include "zisofs.h" /* This should probably be global. */ diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 14d86de6637d..6030956b894b 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -10,20 +10,9 @@ * * isofs directory handling functions */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include - -#include +#include "isofs.h" static int isofs_readdir(struct file *, void *, filldir_t); diff --git a/fs/isofs/export.c b/fs/isofs/export.c index e4252c960871..4af856a7fda7 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -13,11 +13,7 @@ * fs/exportfs/expfs.c. */ -#include -#include -#include -#include -#include +#include "isofs.h" static struct dentry * isofs_export_iget(struct super_block *sb, diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index b9256e65e144..abd7b12eeca7 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -12,29 +12,18 @@ */ #include +#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include #include #include -#include -#include -#include +#include +#include #include -#include -#include +#include "isofs.h" #include "zisofs.h" #define BEQUIET diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h new file mode 100644 index 000000000000..9ce7b51fb614 --- /dev/null +++ b/fs/isofs/isofs.h @@ -0,0 +1,190 @@ +#include +#include +#include +#include + +enum isofs_file_format { + isofs_file_normal = 0, + isofs_file_sparse = 1, + isofs_file_compressed = 2, +}; + +/* + * iso fs inode data in memory + */ +struct iso_inode_info { + unsigned long i_iget5_block; + unsigned long i_iget5_offset; + unsigned int i_first_extent; + unsigned char i_file_format; + unsigned char i_format_parm[3]; + unsigned long i_next_section_block; + unsigned long i_next_section_offset; + off_t i_section_size; + struct inode vfs_inode; +}; + +/* + * iso9660 super-block data in memory + */ +struct isofs_sb_info { + unsigned long s_ninodes; + unsigned long s_nzones; + unsigned long s_firstdatazone; + unsigned long s_log_zone_size; + unsigned long s_max_size; + + unsigned char s_high_sierra; /* A simple flag */ + unsigned char s_mapping; + int s_rock_offset; /* offset of SUSP fields within SU area */ + unsigned char s_rock; + unsigned char s_joliet_level; + unsigned char s_utf8; + unsigned char s_cruft; /* Broken disks with high + byte of length containing + junk */ + unsigned char s_unhide; + unsigned char s_nosuid; + unsigned char s_nodev; + unsigned char s_nocompress; + + mode_t s_mode; + gid_t s_gid; + uid_t s_uid; + struct nls_table *s_nls_iocharset; /* Native language support table */ +}; + +static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct iso_inode_info *ISOFS_I(struct inode *inode) +{ + return container_of(inode, struct iso_inode_info, vfs_inode); +} + +static inline int isonum_711(char *p) +{ + return *(u8 *)p; +} +static inline int isonum_712(char *p) +{ + return *(s8 *)p; +} +static inline unsigned int isonum_721(char *p) +{ + return le16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_722(char *p) +{ + return be16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_723(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le16_to_cpu(get_unaligned((__le16 *)p)); +} +static inline unsigned int isonum_731(char *p) +{ + return le32_to_cpu(get_unaligned((__le32 *)p)); +} +static inline unsigned int isonum_732(char *p) +{ + return be32_to_cpu(get_unaligned((__le32 *)p)); +} +static inline unsigned int isonum_733(char *p) +{ + /* Ignore bigendian datum due to broken mastering programs */ + return le32_to_cpu(get_unaligned((__le32 *)p)); +} +extern int iso_date(char *, int); + +struct inode; /* To make gcc happy */ + +extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); +extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); +extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); + +int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); +int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); + +extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *); +extern struct buffer_head *isofs_bread(struct inode *, sector_t); +extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); + +extern struct inode *isofs_iget(struct super_block *sb, + unsigned long block, + unsigned long offset); + +/* Because the inode number is no longer relevant to finding the + * underlying meta-data for an inode, we are free to choose a more + * convenient 32-bit number as the inode number. The inode numbering + * scheme was recommended by Sergey Vlasov and Eric Lammerts. */ +static inline unsigned long isofs_get_ino(unsigned long block, + unsigned long offset, + unsigned long bufbits) +{ + return (block << (bufbits - 5)) | (offset >> 5); +} + +/* Every directory can have many redundant directory entries scattered + * throughout the directory tree. First there is the directory entry + * with the name of the directory stored in the parent directory. + * Then, there is the "." directory entry stored in the directory + * itself. Finally, there are possibly many ".." directory entries + * stored in all the subdirectories. + * + * In order for the NFS get_parent() method to work and for the + * general consistency of the dcache, we need to make sure the + * "i_iget5_block" and "i_iget5_offset" all point to exactly one of + * the many redundant entries for each directory. We normalize the + * block and offset by always making them point to the "." directory. + * + * Notice that we do not use the entry for the directory with the name + * that is located in the parent directory. Even though choosing this + * first directory is more natural, it is much easier to find the "." + * entry in the NFS get_parent() method because it is implicitly + * encoded in the "extent + ext_attr_length" fields of _all_ the + * redundant entries for the directory. Thus, it can always be + * reached regardless of which directory entry you have in hand. + * + * This works because the "." entry is simply the first directory + * record when you start reading the file that holds all the directory + * records, and this file starts at "extent + ext_attr_length" blocks. + * Because the "." entry is always the first entry listed in the + * directories file, the normalized "offset" value is always 0. + * + * You should pass the directory entry in "de". On return, "block" + * and "offset" will hold normalized values. Only directories are + * affected making it safe to call even for non-directory file + * types. */ +static inline void +isofs_normalize_block_and_offset(struct iso_directory_record* de, + unsigned long *block, + unsigned long *offset) +{ + /* Only directories are normalized. */ + if (de->flags[0] & 2) { + *offset = 0; + *block = (unsigned long)isonum_733(de->extent) + + (unsigned long)isonum_711(de->ext_attr_length); + } +} + +extern struct inode_operations isofs_dir_inode_operations; +extern struct file_operations isofs_dir_operations; +extern struct address_space_operations isofs_symlink_aops; +extern struct export_operations isofs_export_ops; + +/* The following macros are used to check for memory leaks. */ +#ifdef LEAK_CHECK +#define free_s leak_check_free_s +#define malloc leak_check_malloc +#define sb_bread leak_check_bread +#define brelse leak_check_brelse +extern void * leak_check_malloc(unsigned int size); +extern void leak_check_free_s(void * obj, int size); +extern struct buffer_head * leak_check_bread(struct super_block *sb, int block); +extern void leak_check_brelse(struct buffer_head * bh); +#endif /* LEAK_CHECK */ diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index 86c50e22fc87..2931de7f1a6a 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c @@ -6,11 +6,9 @@ * Joliet: Microsoft's Unicode extensions to iso9660 */ -#include +#include #include -#include -#include -#include +#include "isofs.h" /* * Convert Unicode 16 to UTF8 or ASCII. diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index 9569fc44102d..690edf37173c 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -6,20 +6,9 @@ * (C) 1991 Linus Torvalds - minix filesystem */ -#include -#include -#include -#include -#include -#include -#include -#include #include /* Joliet? */ #include -#include -#include - -#include +#include "isofs.h" /* * ok, we cannot use strncmp, as the name is not in our data space. diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 8bdd3e409543..089e79c65585 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -6,17 +6,11 @@ * Rock Ridge Extensions to iso9660 */ -#include -#include -#include -#include -#include #include #include #include -#include -#include +#include "isofs.h" #include "rock.h" /* These functions are designed to read the system areas of a directory record diff --git a/fs/isofs/util.c b/fs/isofs/util.c index 3f6d9c1ac95a..01e1ee7a998b 100644 --- a/fs/isofs/util.c +++ b/fs/isofs/util.c @@ -2,9 +2,7 @@ * linux/fs/isofs/util.c */ -#include -#include -#include +#include "isofs.h" /* * We have to convert from a MM/DD/YY format to the Unix ctime format. @@ -80,4 +78,3 @@ int iso_date(char * p, int flag) } return crtime; } - diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h index 099039d4b10d..47967878bfef 100644 --- a/include/linux/iso_fs.h +++ b/include/linux/iso_fs.h @@ -1,4 +1,3 @@ - #ifndef _ISOFS_FS_H #define _ISOFS_FS_H @@ -163,150 +162,4 @@ struct iso_directory_record { #define ISOFS_SUPER_MAGIC 0x9660 -#ifdef __KERNEL__ -/* Number conversion inlines, named after the section in ISO 9660 - they correspond to. */ - -#include -#include -#include -#include - -static inline struct isofs_sb_info *ISOFS_SB(struct super_block *sb) -{ - return sb->s_fs_info; -} - -static inline struct iso_inode_info *ISOFS_I(struct inode *inode) -{ - return container_of(inode, struct iso_inode_info, vfs_inode); -} - -static inline int isonum_711(char *p) -{ - return *(u8 *)p; -} -static inline int isonum_712(char *p) -{ - return *(s8 *)p; -} -static inline unsigned int isonum_721(char *p) -{ - return le16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_722(char *p) -{ - return be16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_723(char *p) -{ - /* Ignore bigendian datum due to broken mastering programs */ - return le16_to_cpu(get_unaligned((__le16 *)p)); -} -static inline unsigned int isonum_731(char *p) -{ - return le32_to_cpu(get_unaligned((__le32 *)p)); -} -static inline unsigned int isonum_732(char *p) -{ - return be32_to_cpu(get_unaligned((__le32 *)p)); -} -static inline unsigned int isonum_733(char *p) -{ - /* Ignore bigendian datum due to broken mastering programs */ - return le32_to_cpu(get_unaligned((__le32 *)p)); -} -extern int iso_date(char *, int); - -struct inode; /* To make gcc happy */ - -extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); -extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); -extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); - -int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *); -int get_acorn_filename(struct iso_directory_record *, char *, struct inode *); - -extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *); -extern struct buffer_head *isofs_bread(struct inode *, sector_t); -extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); - -extern struct inode *isofs_iget(struct super_block *sb, - unsigned long block, - unsigned long offset); - -/* Because the inode number is no longer relevant to finding the - * underlying meta-data for an inode, we are free to choose a more - * convenient 32-bit number as the inode number. The inode numbering - * scheme was recommended by Sergey Vlasov and Eric Lammerts. */ -static inline unsigned long isofs_get_ino(unsigned long block, - unsigned long offset, - unsigned long bufbits) -{ - return (block << (bufbits - 5)) | (offset >> 5); -} - -/* Every directory can have many redundant directory entries scattered - * throughout the directory tree. First there is the directory entry - * with the name of the directory stored in the parent directory. - * Then, there is the "." directory entry stored in the directory - * itself. Finally, there are possibly many ".." directory entries - * stored in all the subdirectories. - * - * In order for the NFS get_parent() method to work and for the - * general consistency of the dcache, we need to make sure the - * "i_iget5_block" and "i_iget5_offset" all point to exactly one of - * the many redundant entries for each directory. We normalize the - * block and offset by always making them point to the "." directory. - * - * Notice that we do not use the entry for the directory with the name - * that is located in the parent directory. Even though choosing this - * first directory is more natural, it is much easier to find the "." - * entry in the NFS get_parent() method because it is implicitly - * encoded in the "extent + ext_attr_length" fields of _all_ the - * redundant entries for the directory. Thus, it can always be - * reached regardless of which directory entry you have in hand. - * - * This works because the "." entry is simply the first directory - * record when you start reading the file that holds all the directory - * records, and this file starts at "extent + ext_attr_length" blocks. - * Because the "." entry is always the first entry listed in the - * directories file, the normalized "offset" value is always 0. - * - * You should pass the directory entry in "de". On return, "block" - * and "offset" will hold normalized values. Only directories are - * affected making it safe to call even for non-directory file - * types. */ -static inline void -isofs_normalize_block_and_offset(struct iso_directory_record* de, - unsigned long *block, - unsigned long *offset) -{ - /* Only directories are normalized. */ - if (de->flags[0] & 2) { - *offset = 0; - *block = (unsigned long)isonum_733(de->extent) - + (unsigned long)isonum_711(de->ext_attr_length); - } -} - -extern struct inode_operations isofs_dir_inode_operations; -extern struct file_operations isofs_dir_operations; -extern struct address_space_operations isofs_symlink_aops; -extern struct export_operations isofs_export_ops; - -/* The following macros are used to check for memory leaks. */ -#ifdef LEAK_CHECK -#define free_s leak_check_free_s -#define malloc leak_check_malloc -#define sb_bread leak_check_bread -#define brelse leak_check_brelse -extern void * leak_check_malloc(unsigned int size); -extern void leak_check_free_s(void * obj, int size); -extern struct buffer_head * leak_check_bread(struct super_block *sb, int block); -extern void leak_check_brelse(struct buffer_head * bh); -#endif /* LEAK_CHECK */ - -#endif /* __KERNEL__ */ - #endif diff --git a/include/linux/iso_fs_i.h b/include/linux/iso_fs_i.h deleted file mode 100644 index 59065e939eaa..000000000000 --- a/include/linux/iso_fs_i.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _ISO_FS_I -#define _ISO_FS_I - -#include - -enum isofs_file_format { - isofs_file_normal = 0, - isofs_file_sparse = 1, - isofs_file_compressed = 2, -}; - -/* - * iso fs inode data in memory - */ -struct iso_inode_info { - unsigned long i_iget5_block; - unsigned long i_iget5_offset; - unsigned int i_first_extent; - unsigned char i_file_format; - unsigned char i_format_parm[3]; - unsigned long i_next_section_block; - unsigned long i_next_section_offset; - off_t i_section_size; - struct inode vfs_inode; -}; - -#endif diff --git a/include/linux/iso_fs_sb.h b/include/linux/iso_fs_sb.h deleted file mode 100644 index 043b97b55b8d..000000000000 --- a/include/linux/iso_fs_sb.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ISOFS_FS_SB -#define _ISOFS_FS_SB - -/* - * iso9660 super-block data in memory - */ -struct isofs_sb_info { - unsigned long s_ninodes; - unsigned long s_nzones; - unsigned long s_firstdatazone; - unsigned long s_log_zone_size; - unsigned long s_max_size; - - unsigned char s_high_sierra; /* A simple flag */ - unsigned char s_mapping; - int s_rock_offset; /* offset of SUSP fields within SU area */ - unsigned char s_rock; - unsigned char s_joliet_level; - unsigned char s_utf8; - unsigned char s_cruft; /* Broken disks with high - byte of length containing - junk */ - unsigned char s_unhide; - unsigned char s_nosuid; - unsigned char s_nodev; - unsigned char s_nocompress; - - mode_t s_mode; - gid_t s_gid; - uid_t s_uid; - struct nls_table *s_nls_iocharset; /* Native language support table */ -}; - -#endif -- cgit v1.2.3 From 5fc3e624ad7278604628c598e92aa77c67064166 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 27 Apr 2005 15:39:03 -0700 Subject: [PATCH] NFS4: Don't use __user with compat_uptr_t The attached patch removes __user from compat_uptr_t types in the NFS4 mount 32-bit->64-bit compatibility structures. Signed-Off-By: David Howells Signed-off-by: Linus Torvalds --- fs/compat.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/compat.c b/fs/compat.c index 67c0b94d1148..728cd8365384 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -809,7 +809,7 @@ static void *do_smb_super_data_conv(void *raw_data) struct compat_nfs_string { compat_uint_t len; - compat_uptr_t __user data; + compat_uptr_t data; }; static inline void compat_nfs_string(struct nfs_string *dst, @@ -834,10 +834,10 @@ struct compat_nfs4_mount_data_v1 { struct compat_nfs_string mnt_path; struct compat_nfs_string hostname; compat_uint_t host_addrlen; - compat_uptr_t __user host_addr; + compat_uptr_t host_addr; compat_int_t proto; compat_int_t auth_flavourlen; - compat_uptr_t __user auth_flavours; + compat_uptr_t auth_flavours; }; static int do_nfs4_super_data_conv(void *raw_data) -- cgit v1.2.3 From 18c8baff8fe151ea02e00047afc369ee31939e9b Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 28 Apr 2005 15:17:19 -0700 Subject: [PATCH] Fix error recovery path for arch_setup_additional_pages If arch_setup_additional_pages fails, the error path will do some double-frees. This fixes it. Signed-off-by: Roland McGrath Signed-off-by: Linus Torvalds --- fs/binfmt_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 6ae62cbf7c2e..ce9423bb2de3 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -945,7 +945,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) retval = arch_setup_additional_pages(bprm, executable_stack); if (retval < 0) { send_sig(SIGKILL, current, 0); - goto out_free_dentry; + goto out; } #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ -- cgit v1.2.3 From 1da0c78b32abe122a959d2a57ba3d41563d8e39f Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: Only send POSIX ACL calls to server if server claims to support that capability bit Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/xattr.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 549afa184fd6..9a41bee11c5a 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -161,18 +161,20 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, strlen(POSIX_ACL_XATTR_ACCESS)); if (temp == 0) { #ifdef CONFIG_CIFS_POSIX - rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, - (const int)value_size, ACL_TYPE_ACCESS, - cifs_sb->local_nls); + if(sb->s_flags & MS_POSIXACL) + rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, + ea_value, (const int)value_size, + ACL_TYPE_ACCESS,cifs_sb->local_nls); cFYI(1,("set POSIX ACL rc %d",rc)); #else cFYI(1,("set POSIX ACL not supported")); #endif } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { #ifdef CONFIG_CIFS_POSIX - rc = CIFSSMBSetPosixACL(xid, pTcon,full_path,ea_value, - (const int)value_size, ACL_TYPE_DEFAULT, - cifs_sb->local_nls); + if(sb->s_flags & MS_POSIXACL) + rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, + ea_value, (const int)value_size, + ACL_TYPE_DEFAULT, cifs_sb->local_nls); cFYI(1,("set POSIX default ACL rc %d",rc)); #else cFYI(1,("set default POSIX ACL not supported")); @@ -248,7 +250,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, buf_size, cifs_sb->local_nls); } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { #ifdef CONFIG_CIFS_POSIX - rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, + if(sb->s_flags & MS_POSIXACL) + rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, ea_value, buf_size, ACL_TYPE_ACCESS, cifs_sb->local_nls); #else @@ -256,7 +259,8 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, #endif /* CONFIG_CIFS_POSIX */ } else if(strncmp(ea_name,POSIX_ACL_XATTR_DEFAULT,strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { #ifdef CONFIG_CIFS_POSIX - rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, + if(sb->s_flags & MS_POSIXACL) + rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, ea_value, buf_size, ACL_TYPE_DEFAULT, cifs_sb->local_nls); #else -- cgit v1.2.3 From f654bac2227adc5c6956405290eeb4f81f09e9ff Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: add support for chattr/lsattr in new CIFS POSIX extensions Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 9 +++++- fs/cifs/cifsfs.h | 6 ++-- fs/cifs/cifspdu.h | 69 ++++++++++++++++++++++++++++++++++++++---- fs/cifs/cifsproto.h | 4 ++- fs/cifs/cifssmb.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++- fs/cifs/ioctl.c | 52 ++++++++++++++++++++++++++++++-- 6 files changed, 212 insertions(+), 14 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 5316c8dd6bff..7fd02697b12e 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,7 +1,14 @@ -Version 1.31 +Version 1.32 ------------ Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one transact response for an SMB request and search entry split across two frames. +Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) +as new protocol extensions. Do not send Get/Set calls for POSIX ACLs +unless server explicitly claims to support them in CIFS Unix extensions +POSIX ACL capability bit. + +Version 1.31 +------------ Fix updates of DOS attributes and time fields so that files on NT4 servers do not get marked delete on close. Display sizes of cifs buffer pools in cifs stats. Fix oops in unmount when cifsd thread being killed by diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 451f18af3206..e0e46f4bff97 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -91,8 +91,10 @@ extern int cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname); extern int cifs_removexattr(struct dentry *, const char *); extern int cifs_setxattr(struct dentry *, const char *, const void *, - size_t, int); + size_t, int); extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); -#define CIFS_VERSION "1.31" +extern int cifs_ioctl (struct inode * inode, struct file * filep, + unsigned int command, unsigned long arg); +#define CIFS_VERSION "1.32" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index bcd4a6136f08..085109d2b55e 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -762,6 +762,16 @@ typedef struct smb_com_lock_req { LOCKING_ANDX_RANGE Locks[1]; } LOCK_REQ; + +typedef struct cifs_posix_lock { + __le16 lock_type; /* 0 = Read, 1 = Write, 2 = Unlock */ + __le16 lock_flags; /* 1 = Wait (only valid for setlock) */ + __le32 pid; + __le64 start; + __le64 length; + /* BB what about additional owner info to identify network client */ +} CIFS_POSIX_LOCK; + typedef struct smb_com_lock_rsp { struct smb_hdr hdr; /* wct = 2 */ __u8 AndXCommand; @@ -1098,6 +1108,8 @@ struct smb_t2_rsp { #define SMB_QUERY_POSIX_ACL 0x204 #define SMB_QUERY_XATTR 0x205 #define SMB_QUERY_ATTR_FLAGS 0x206 /* append,immutable etc. */ +#define SMB_QUERY_POSIX_PERMISSION 0x207 +#define SMB_QUERY_POSIX_LOCK 0x208 #define SMB_QUERY_FILE_INTERNAL_INFO 0x3ee #define SMB_QUERY_FILE_ACCESS_INFO 0x3f0 #define SMB_QUERY_FILE_NAME_INFO2 0x3f1 /* 0x30 bytes */ @@ -1116,6 +1128,7 @@ struct smb_t2_rsp { #define SMB_SET_POSIX_ACL 0x204 #define SMB_SET_XATTR 0x205 #define SMB_SET_ATTR_FLAGS 0x206 /* append, immutable etc. */ +#define SMB_SET_POSIX_LOCK 0x208 #define SMB_SET_FILE_BASIC_INFO2 0x3ec #define SMB_SET_FILE_RENAME_INFORMATION 0x3f2 /* BB check if qpathinfo level too */ #define SMB_FILE_ALL_INFO2 0x3fa @@ -1237,9 +1250,27 @@ struct smb_com_transaction2_sfi_rsp { struct smb_hdr hdr; /* wct = 10 + SetupCount */ struct trans2_resp t2; __u16 ByteCount; - __u16 Reserved2; /* parameter word reserved - present for infolevels > 100 */ + __u16 Reserved2; /* parameter word reserved - + present for infolevels > 100 */ +}; + +struct smb_t2_qfi_req { + struct smb_hdr hdr; + struct trans2_req t2; + __u8 Pad; + __u16 Pad1; + __u16 Fid; + __le16 InformationLevel; + __u16 Pad2; }; +struct smb_t2_qfi_rsp { + struct smb_hdr hdr; /* wct = 10 + SetupCount */ + struct trans2_resp t2; + __u16 ByteCount; + __u16 Reserved2; /* parameter word reserved - + present for infolevels > 100 */ +}; /* * Flags on T2 FINDFIRST and FINDNEXT @@ -1524,8 +1555,9 @@ typedef struct { } FILE_SYSTEM_UNIX_INFO; /* Unix extensions info, level 0x200 */ /* Linux/Unix extensions capability flags */ #define CIFS_UNIX_FCNTL_CAP 0x00000001 /* support for fcntl locks */ -#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 -#define CIFS_UNIX_XATTR_CAP 0x00000004 /*support for new namespace*/ +#define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ +#define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ +#define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ typedef struct { /* For undefined recommended transfer size return -1 in that field */ @@ -1971,14 +2003,39 @@ struct xsymlink { char path[1024]; }; -typedef struct { +typedef struct file_xattr_info { /* BB do we need another field for flags? BB */ __u32 xattr_name_len; __u32 xattr_value_len; char xattr_name[0]; /* followed by xattr_value[xattr_value_len], no pad */ -} FILE_XATTR_INFO; /* extended attribute, info level 205 */ - +} FILE_XATTR_INFO; /* extended attribute, info level 0x205 */ + + +/* flags for chattr command */ +#define EXT_SECURE_DELETE 0x00000001 /* EXT3_SECRM_FL */ +#define EXT_ENABLE_UNDELETE 0x00000002 /* EXT3_UNRM_FL */ +/* Reserved for compress file 0x4 */ +#define EXT_SYNCHRONOUS 0x00000008 /* EXT3_SYNC_FL */ +#define EXT_IMMUTABLE_FL 0x00000010 /* EXT3_IMMUTABLE_FL */ +#define EXT_OPEN_APPEND_ONLY 0x00000020 /* EXT3_APPEND_FL */ +#define EXT_DO_NOT_BACKUP 0x00000040 /* EXT3_NODUMP_FL */ +#define EXT_NO_UPDATE_ATIME 0x00000080 /* EXT3_NOATIME_FL */ +/* 0x100 through 0x800 reserved for compression flags and are GET-ONLY */ +#define EXT_HASH_TREE_INDEXED_DIR 0x00001000 /* GET-ONLY EXT3_INDEX_FL */ +/* 0x2000 reserved for IMAGIC_FL */ +#define EXT_JOURNAL_THIS_FILE 0x00004000 /* GET-ONLY EXT3_JOURNAL_DATA_FL */ +/* 0x8000 reserved for EXT3_NOTAIL_FL */ +#define EXT_SYNCHRONOUS_DIR 0x00010000 /* EXT3_DIRSYNC_FL */ +#define EXT_TOPDIR 0x00020000 /* EXT3_TOPDIR_FL */ + +#define EXT_SET_MASK 0x000300FF +#define EXT_GET_MASK 0x0003DFFF + +typedef struct file_chattr_info { + __le64 mask; /* list of all possible attribute bits */ + __le64 mode; /* list of actual attribute bits on this inode */ +} FILE_CHATTR_INFO; /* ext attributes (chattr, chflags) level 0x206 */ #endif diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 787eef4d86d3..82ae59d7cf9d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -264,6 +264,8 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *fileName, const char *local_acl, const int buflen, const int acl_type, const struct nls_table *nls_codepage); -int cifs_ioctl (struct inode * inode, struct file * filep, +extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, + const int netfid, __u64 * pExtAttrBits, __u64 *pMask); +extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index df6a619a6821..36d3c128a58b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2072,7 +2072,91 @@ setACLerrorExit: return rc; } -#endif +/* BB fix tabs in this function FIXME BB */ +int +CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, + const int netfid, __u64 * pExtAttrBits, __u64 *pMask) +{ + int rc = 0; + struct smb_t2_qfi_req *pSMB = NULL; + struct smb_t2_qfi_rsp *pSMBr = NULL; + int bytes_returned; + __u16 params, byte_count; + + cFYI(1,("In GetExtAttr")); + if(tcon == NULL) + return -ENODEV; + +GetExtAttrRetry: + rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, + (void **) &pSMBr); + if (rc) + return rc; + + params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */; + pSMB->t2.TotalDataCount = 0; + pSMB->t2.MaxParameterCount = cpu_to_le16(2); + /* BB find exact max data count below from sess structure BB */ + pSMB->t2.MaxDataCount = cpu_to_le16(4000); + pSMB->t2.MaxSetupCount = 0; + pSMB->t2.Reserved = 0; + pSMB->t2.Flags = 0; + pSMB->t2.Timeout = 0; + pSMB->t2.Reserved2 = 0; + pSMB->t2.ParameterOffset = cpu_to_le16(offsetof( + struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); + pSMB->t2.DataCount = 0; + pSMB->t2.DataOffset = 0; + pSMB->t2.SetupCount = 1; + pSMB->t2.Reserved3 = 0; + pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); + byte_count = params + 3 /* pad */ ; + pSMB->t2.TotalParameterCount = cpu_to_le16(params); + pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; + pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); + pSMB->Pad1 = 0; + pSMB->Pad2 = 0; + pSMB->Fid = netfid; + pSMB->hdr.smb_buf_length += byte_count; + pSMB->t2.ByteCount = cpu_to_le16(byte_count); + + rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, + (struct smb_hdr *) pSMBr, &bytes_returned, 0); + if (rc) { + cFYI(1, ("error %d in GetExtAttr", rc)); + } else { + /* decode response */ + rc = validate_t2((struct smb_t2_rsp *)pSMBr); + if (rc || (pSMBr->ByteCount < 2)) + /* BB also check enough total bytes returned */ + /* If rc should we check for EOPNOSUPP and + disable the srvino flag? or in caller? */ + rc = -EIO; /* bad smb */ + else { + __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); + __u16 count = le16_to_cpu(pSMBr->t2.DataCount); + struct file_chattr_info * pfinfo; + /* BB Do we need a cast or hash here ? */ + if(count != 16) { + cFYI(1, ("Illegal size ret in GetExtAttr")); + rc = -EIO; + goto GetExtAttrOut; + } + pfinfo = (struct file_chattr_info *) + (data_offset + (char *) &pSMBr->hdr.Protocol); + *pExtAttrBits = le64_to_cpu(pfinfo->mode); + *pMask = le64_to_cpu(pfinfo->mask); + } + } +GetExtAttrOut: + cifs_buf_release(pSMB); + if (rc == -EAGAIN) + goto GetExtAttrRetry; + return rc; +} + + +#endif /* CONFIG_POSIX */ int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index b4b8e201d428..7b84b2bb8c4a 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -20,6 +20,7 @@ * along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include #include #include "cifspdu.h" @@ -32,18 +33,63 @@ int cifs_ioctl (struct inode * inode, struct file * filep, { int rc = -ENOTTY; /* strange error - but the precedent */ #ifdef CONFIG_CIFS_POSIX + __u64 ExtAttrBits = 0; + __u64 ExtAttrMask = 0; + __u64 caps; +#endif /* CONFIG_CIFS_POSIX */ + int xid; + struct cifs_sb_info *cifs_sb; + struct cifsTconInfo *tcon; + struct cifsFileInfo *pSMBFile = + (struct cifsFileInfo *)filep->private_data; + + xid = GetXid(); + + cifs_sb = CIFS_SB(inode->i_sb); + tcon = cifs_sb->tcon; + if (pSMBFile == NULL) + goto cifs_ioctl_out; + +#ifdef CONFIG_CIFS_POSIX + if(tcon) + caps = le64_to_cpu(tcon->fsUnixInfo.Capability); + else { + rc = -EIO; + goto cifs_ioctl_out; + } + cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); switch(command) { case EXT2_IOC_GETFLAGS: - cFYI(1,("get flags not implemented yet")); - return -EOPNOTSUPP; + if(CIFS_UNIX_EXTATTR_CAP & caps) { + rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + &ExtAttrBits, &ExtAttrMask); + if(rc == 0) + rc = put_user(ExtAttrBits & + EXT2_FL_USER_VISIBLE, + (int __user *)arg); + } + break; + case EXT2_IOC_SETFLAGS: + if(CIFS_UNIX_EXTATTR_CAP & caps) { + if(get_user(ExtAttrBits,(int __user *)arg)) { + rc = -EFAULT; + goto cifs_ioctl_out; + } + /* rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + extAttrBits, &ExtAttrMask);*/ + + } cFYI(1,("set flags not implemented yet")); - return -EOPNOTSUPP; + break; default: cFYI(1,("unsupported ioctl")); return rc; } #endif /* CONFIG_CIFS_POSIX */ + +cifs_ioctl_out: + FreeXid(xid); return rc; } -- cgit v1.2.3 From 75cf6bdc52d86ca815f1129529e43f0d904b18d5 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: Gracefully turn off serverino (when serverino is enabled on mount) Old servers such as NT4 do not support this level of FindFirst (and retry with a lower infolevel) Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/netmisc.c | 2 +- fs/cifs/readdir.c | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 4e34c89cec5d..dfaabc8d8fb6 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -206,7 +206,7 @@ static const struct { { ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { - ERRDOS, 87, NT_STATUS_INVALID_INFO_CLASS}, { + ERRDOS, ERRinvlevel, NT_STATUS_INVALID_INFO_CLASS}, { ERRDOS, 24, NT_STATUS_INFO_LENGTH_MISMATCH}, { ERRHRD, ERRgeneral, NT_STATUS_ACCESS_VIOLATION}, { ERRHRD, ERRgeneral, NT_STATUS_IN_PAGE_ERROR}, { diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index f8bea395ec9e..07838a5ba3a1 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -323,6 +323,7 @@ static int initiate_cifs_search(const int xid, struct file *file) cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); +ffirst_retry: /* test for Unix extensions */ if (pTcon->ses->capabilities & CAP_UNIX) { cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; @@ -336,6 +337,11 @@ static int initiate_cifs_search(const int xid, struct file *file) &cifsFile->netfid, &cifsFile->srch_inf); if(rc == 0) cifsFile->invalidHandle = FALSE; + if((rc == -EOPNOTSUPP) && + (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { + cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM; + goto ffirst_retry; + } kfree(full_path); return rc; } -- cgit v1.2.3 From c67593a03129967eae8939c4899767182eb6d6cd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:04 -0700 Subject: [PATCH] cifs: Enable ioctl support in POSIX extensions to handle lsattr remove sparse warnings, unnecessary pad in QueryFileInfo and redundant function define. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 8 ++++++++ fs/cifs/cifspdu.h | 2 -- fs/cifs/cifsproto.h | 2 -- fs/cifs/cifssmb.c | 13 ++++++------- fs/cifs/ioctl.c | 1 + 5 files changed, 15 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 5082fce3c566..ae48ef042977 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -559,6 +559,10 @@ struct file_operations cifs_file_ops = { .flush = cifs_flush, .mmap = cifs_file_mmap, .sendfile = generic_file_sendfile, +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ + #ifdef CONFIG_CIFS_EXPERIMENTAL .readv = generic_file_readv, .writev = generic_file_writev, @@ -579,6 +583,10 @@ struct file_operations cifs_file_direct_ops = { .fsync = cifs_fsync, .flush = cifs_flush, .sendfile = generic_file_sendfile, /* BB removeme BB */ +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ + #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 085109d2b55e..5b352890f092 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1258,10 +1258,8 @@ struct smb_t2_qfi_req { struct smb_hdr hdr; struct trans2_req t2; __u8 Pad; - __u16 Pad1; __u16 Fid; __le16 InformationLevel; - __u16 Pad2; }; struct smb_t2_qfi_rsp { diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 82ae59d7cf9d..1b0070dfc51c 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -266,6 +266,4 @@ extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const struct nls_table *nls_codepage); extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, const int netfid, __u64 * pExtAttrBits, __u64 *pMask); -extern int cifs_ioctl (struct inode * inode, struct file * filep, - unsigned int command, unsigned long arg); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 36d3c128a58b..237e3bf94bfe 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2093,9 +2093,9 @@ GetExtAttrRetry: if (rc) return rc; - params = 2 /* level */ +2 /* fid */ + 2 /* rsrvd */; + params = 2 /* level */ +2 /* fid */; pSMB->t2.TotalDataCount = 0; - pSMB->t2.MaxParameterCount = cpu_to_le16(2); + pSMB->t2.MaxParameterCount = cpu_to_le16(4); /* BB find exact max data count below from sess structure BB */ pSMB->t2.MaxDataCount = cpu_to_le16(4000); pSMB->t2.MaxSetupCount = 0; @@ -2103,19 +2103,18 @@ GetExtAttrRetry: pSMB->t2.Flags = 0; pSMB->t2.Timeout = 0; pSMB->t2.Reserved2 = 0; - pSMB->t2.ParameterOffset = cpu_to_le16(offsetof( - struct smb_com_transaction2_qpi_req ,InformationLevel) - 4); + pSMB->t2.ParameterOffset = cpu_to_le16(offsetof(struct smb_t2_qfi_req, + Fid) - 4); pSMB->t2.DataCount = 0; pSMB->t2.DataOffset = 0; pSMB->t2.SetupCount = 1; pSMB->t2.Reserved3 = 0; pSMB->t2.SubCommand = cpu_to_le16(TRANS2_QUERY_FILE_INFORMATION); - byte_count = params + 3 /* pad */ ; + byte_count = params + 1 /* pad */ ; pSMB->t2.TotalParameterCount = cpu_to_le16(params); pSMB->t2.ParameterCount = pSMB->t2.TotalParameterCount; pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_ATTR_FLAGS); - pSMB->Pad1 = 0; - pSMB->Pad2 = 0; + pSMB->Pad = 0; pSMB->Fid = netfid; pSMB->hdr.smb_buf_length += byte_count; pSMB->t2.ByteCount = cpu_to_le16(byte_count); diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 7b84b2bb8c4a..a4f1c34a8dc7 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -27,6 +27,7 @@ #include "cifsglob.h" #include "cifsproto.h" #include "cifs_debug.h" +#include "cifsfs.h" int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) -- cgit v1.2.3 From ad009ac96509e005d9978d0ae9e9ec4d63ad2990 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:05 -0700 Subject: [PATCH] cifs: Fix multiuser packet signing to use the right sequence number and mac session key Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 3 ++- fs/cifs/cifsencrypt.c | 16 ++++++++-------- fs/cifs/cifsglob.h | 11 ++++++----- fs/cifs/cifsproto.h | 2 +- fs/cifs/connect.c | 28 ++++++++++++++++++++-------- fs/cifs/transport.c | 22 +++++++++++++--------- 6 files changed, 50 insertions(+), 32 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 7fd02697b12e..43b3119a16ed 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -5,7 +5,8 @@ transact response for an SMB request and search entry split across two frames. Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) as new protocol extensions. Do not send Get/Set calls for POSIX ACLs unless server explicitly claims to support them in CIFS Unix extensions -POSIX ACL capability bit. +POSIX ACL capability bit. Fix packet signing when multiuser mounting with +different users from the same client to the same server. Version 1.31 ------------ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 78829e7d8cd0..1959c7c4b185 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -50,7 +50,7 @@ static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char return 0; } -int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, +int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct TCP_Server_Info * server, __u32 * pexpected_response_sequence_number) { int rc = 0; @@ -59,21 +59,21 @@ int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses, /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */ /* BB remember to add code to save expected sequence number in midQ entry BB */ - if((cifs_pdu == NULL) || (ses == NULL)) + if((cifs_pdu == NULL) || (server == NULL)) return -EINVAL; if((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) return rc; spin_lock(&GlobalMid_Lock); - cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number); + cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number); cifs_pdu->Signature.Sequence.Reserved = 0; - *pexpected_response_sequence_number = ses->sequence_number++; - ses->sequence_number++; + *pexpected_response_sequence_number = server->sequence_number++; + server->sequence_number++; spin_unlock(&GlobalMid_Lock); - rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature); + rc = cifs_calculate_signature(cifs_pdu, server->mac_signing_key,smb_signature); if(rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -190,7 +190,7 @@ int CalcNTLMv2_partial_mac_key(struct cifsSesInfo * ses, struct nls_table * nls_ hmac_md5_update((const unsigned char *) unicode_buf, (user_name_len+dom_name_len)*2,&ctx); - hmac_md5_final(ses->mac_signing_key,&ctx); + hmac_md5_final(ses->server->mac_signing_key,&ctx); kfree(ucase_buf); kfree(unicode_buf); return 0; @@ -200,7 +200,7 @@ void CalcNTLMv2_response(const struct cifsSesInfo * ses,char * v2_session_respon struct HMACMD5Context context; memcpy(v2_session_response + 8, ses->server->cryptKey,8); /* gen_blob(v2_session_response + 16); */ - hmac_md5_init_limK_to_64(ses->mac_signing_key, 16, &context); + hmac_md5_init_limK_to_64(ses->server->mac_signing_key, 16, &context); hmac_md5_update(ses->server->cryptKey,8,&context); /* hmac_md5_update(v2_session_response+16)client thing,8,&context); */ /* BB fix */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 69aff1a7da9b..1b3082d79379 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -149,6 +149,8 @@ struct TCP_Server_Info { __u16 timeZone; char cryptKey[CIFS_CRYPTO_KEY_SIZE]; char workstation_RFC1001_name[16]; /* 16th byte is always zero */ + __u32 sequence_number; /* needed for CIFS PDU signature */ + char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; }; /* @@ -174,17 +176,16 @@ struct cifsSesInfo { struct TCP_Server_Info *server; /* pointer to server info */ atomic_t inUse; /* # of mounts (tree connections) on this ses */ enum statusEnum status; - __u32 sequence_number; /* needed for CIFS PDU signature */ __u16 ipc_tid; /* special tid for connection to IPC share */ __u16 flags; - char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16]; - char *serverOS; /* name of operating system underlying the server */ - char *serverNOS; /* name of network operating system that the server is running */ + char *serverOS; /* name of operating system underlying server */ + char *serverNOS; /* name of network operating system of server */ char *serverDomain; /* security realm of server */ int Suid; /* remote smb uid */ uid_t linux_uid; /* local Linux uid */ int capabilities; - char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for tcp names - will ipv6 and sctp addresses fit here?? */ + char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for + TCP names - will ipv6 and sctp addresses fit? */ char userName[MAX_USERNAME_SIZE + 1]; char domainName[MAX_USERNAME_SIZE + 1]; char * password; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 1b0070dfc51c..dd95c2bcbc25 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -230,7 +230,7 @@ extern void tconInfoFree(struct cifsTconInfo *); extern int cifs_reconnect(struct TCP_Server_Info *server); -extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *); +extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *,__u32 *); extern int cifs_verify_signature(struct smb_hdr *, const char * mac_key, __u32 expected_sequence_number); extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 40470b9d5477..814e709ca0ca 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -182,7 +182,8 @@ cifs_reconnect(struct TCP_Server_Info *server) spin_lock(&GlobalMid_Lock); if(server->tcpStatus != CifsExiting) server->tcpStatus = CifsGood; - spin_unlock(&GlobalMid_Lock); + server->sequence_number = 0; + spin_unlock(&GlobalMid_Lock); /* atomic_set(&server->inFlight,0);*/ wake_up(&server->response_q); } @@ -1352,6 +1353,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, } else rc = 0; memcpy(srvTcp->workstation_RFC1001_name, volume_info.source_rfc1001_name,16); + srvTcp->sequence_number = 0; } } @@ -2959,6 +2961,7 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, int rc = 0; char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; int ntlmv2_flag = FALSE; + int first_time = 0; /* what if server changes its buffer size after dropping the session? */ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ { @@ -2977,12 +2980,13 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, spin_unlock(&GlobalMid_Lock); } + first_time = 1; } if (!rc) { pSesInfo->capabilities = pSesInfo->server->capabilities; if(linuxExtEnabled == 0) pSesInfo->capabilities &= (~CAP_UNIX); - pSesInfo->sequence_number = 0; + /* pSesInfo->sequence_number = 0;*/ cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d", pSesInfo->server->secMode, pSesInfo->server->capabilities, @@ -3015,7 +3019,10 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, v2_response = kmalloc(16 + 64 /* blob */, GFP_KERNEL); if(v2_response) { CalcNTLMv2_response(pSesInfo,v2_response); -/* cifs_calculate_ntlmv2_mac_key(pSesInfo->mac_signing_key, response, ntlm_session_key, */ + /* if(first_time) + cifs_calculate_ntlmv2_mac_key( + pSesInfo->server->mac_signing_key, + response, ntlm_session_key, */ kfree(v2_response); /* BB Put dummy sig in SessSetup PDU? */ } else { @@ -3028,9 +3035,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, pSesInfo->server->cryptKey, ntlm_session_key); - cifs_calculate_mac_key(pSesInfo->mac_signing_key, - ntlm_session_key, - pSesInfo->password); + if(first_time) + cifs_calculate_mac_key( + pSesInfo->server->mac_signing_key, + ntlm_session_key, + pSesInfo->password); } /* for better security the weaker lanman hash not sent in AuthSessSetup so we no longer calculate it */ @@ -3046,8 +3055,11 @@ int cifs_setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, pSesInfo->server->cryptKey, ntlm_session_key); - cifs_calculate_mac_key(pSesInfo->mac_signing_key, - ntlm_session_key, pSesInfo->password); + if(first_time) + cifs_calculate_mac_key( + pSesInfo->server->mac_signing_key, + ntlm_session_key, pSesInfo->password); + rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info); } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index af13e526b150..a9e4f989b7f7 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -346,7 +346,7 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, } /* BB can we sign efficiently in this path? */ - rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); midQ->midState = MID_REQUEST_SUBMITTED; /* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, @@ -475,7 +475,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, return -EIO; } - rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number); + rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); midQ->midState = MID_REQUEST_SUBMITTED; rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, @@ -559,8 +559,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } if (receive_len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { - cERROR(1, - ("Frame too large received. Length: %d Xid: %d", + cERROR(1, ("Frame too large received. Length: %d Xid: %d", receive_len, xid)); rc = -EIO; } else { /* rcvd frame is ok */ @@ -575,15 +574,20 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, dump_smb(out_buf, 92); /* convert the length into a more usable form */ if((receive_len > 24) && - (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) { - rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */ - if(rc) - cFYI(1,("Unexpected signature received from server")); + (ses->server->secMode & (SECMODE_SIGN_REQUIRED | + SECMODE_SIGN_ENABLED))) { + rc = cifs_verify_signature(out_buf, + ses->server->mac_signing_key, + midQ->sequence_number+1); + if(rc) { + cERROR(1,("Unexpected packet signature received from server")); + /* BB FIXME - add code to kill session here */ + } } *pbytes_returned = out_buf->smb_buf_length; - /* BB special case reconnect tid and reconnect uid here? */ + /* BB special case reconnect tid and uid here? */ rc = map_smb_to_linux_error(out_buf); /* convert ByteCount if necessary */ -- cgit v1.2.3 From cbe0476fa6a76b01b79e7c117963d45ed0a28758 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:05 -0700 Subject: [PATCH] cifs: fix rare oops in cifs_close Protect access to cifs file list in cifs_close path Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 3 ++- fs/cifs/file.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 43b3119a16ed..ce16b0ae772e 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -6,7 +6,8 @@ Add support for lsattr (getting ext2/ext3/reiserfs attr flags from the server) as new protocol extensions. Do not send Get/Set calls for POSIX ACLs unless server explicitly claims to support them in CIFS Unix extensions POSIX ACL capability bit. Fix packet signing when multiuser mounting with -different users from the same client to the same server. +different users from the same client to the same server. Fix oops in +cifs_close. Version 1.31 ------------ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index dcab7cf1b53b..9c7755053099 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -465,8 +465,10 @@ int cifs_close(struct inode *inode, struct file *file) write_lock(&file->f_owner.lock); } } + write_lock(&GlobalSMBSeslock); list_del(&pSMBFile->flist); list_del(&pSMBFile->tlist); + write_unlock(&GlobalSMBSeslock); write_unlock(&file->f_owner.lock); kfree(pSMBFile->search_resume_name); kfree(file->private_data); -- cgit v1.2.3 From 6a0b48245a135cd132e747815854e3999967f8a7 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:05 -0700 Subject: [PATCH] cifs: Add new mount parm mapchars For handling seven special characters that shells use for filenames. This first parts implements conversions from Unicode. Signed-off-by: Steve French Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 4 ++- fs/cifs/README | 11 +++++++++ fs/cifs/TODO | 19 ++++++++------- fs/cifs/cifs_fs_sb.h | 1 + fs/cifs/cifsproto.h | 2 ++ fs/cifs/connect.c | 7 ++++++ fs/cifs/misc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/cifs/readdir.c | 15 ++++++++++-- 8 files changed, 116 insertions(+), 12 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index ce16b0ae772e..412b6d243d53 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -7,7 +7,9 @@ as new protocol extensions. Do not send Get/Set calls for POSIX ACLs unless server explicitly claims to support them in CIFS Unix extensions POSIX ACL capability bit. Fix packet signing when multiuser mounting with different users from the same client to the same server. Fix oops in -cifs_close. +cifs_close. Add mount option for remapping reserved characters in +filenames (also allow recognizing files with created by SFU which have any +of these seven reserved characters to be recognized). Version 1.31 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index 0f20edc935b5..83e054576258 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -376,6 +376,17 @@ A partial list of the supported mount options follows: attributes) to the server (default) e.g. via setfattr and getfattr utilities. nouser_xattr Do not allow getfattr/setfattr to get/set xattrs + mapchars Translate the seven reserved characters + *?<>|:\ + to the remap range (above 0xF000), which also + allows the CIFS client to recognize files created with + such characters by Windows's POSIX emulation. This can + also be useful when mounting to most versions of Samba + (which also forbids creating and opening files + whose names contain any of these seven characters). + This has no effect if the server does not support + Unicode on the wire. + nomapchars Do not translate any of these seven characters (default). The mount.cifs mount helper also accepts a few mount options before -o including: diff --git a/fs/cifs/TODO b/fs/cifs/TODO index f4e3e1f67ee4..a69227415a73 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -version 1.22 July 30, 2004 +version 1.32 April 3, 2005 A Partial List of Missing Features ================================== @@ -14,7 +14,7 @@ b) Better pam/winbind integration (e.g. to handle uid mapping better) c) multi-user mounts - multiplexed sessionsetups over single vc -(ie tcp session) - prettying up needed, and more testing needed +(ie tcp session) - more testing needed d) Kerberos/SPNEGO session setup support - (started) @@ -67,12 +67,15 @@ q) implement support for security and trusted categories of xattrs r) Implement O_DIRECT flag on open (already supported on mount) -KNOWN BUGS (updated December 10, 2004) +KNOWN BUGS (updated April 3, 2005) ==================================== +See http://bugzilla.samba.org - search on product "CifsVFS" for +current bug list. + 1) existing symbolic links (Windows reparse points) are recognized but can not be created remotely. They are implemented for Samba and those that -support the CIFS Unix extensions but Samba has a bug currently handling -symlink text beginning with slash +support the CIFS Unix extensions, although earlier versions of Samba +overly restrict the pathnames. 2) follow_link and readdir code does not follow dfs junctions but recognizes them 3) create of new files to FAT partitions on Windows servers can @@ -98,7 +101,5 @@ there are some easy changes that can be done to parallelize sequential writes, and when signing is disabled to request larger read sizes (larger than negotiated size) and send larger write sizes to modern servers. -4) More exhaustively test the recently added NT4 support against various -NT4 service pack levels, and fix cifs_setattr for setting file times and -size to fall back to level 1 when error invalid level returned. - +4) More exhaustively test against less common servers. More testing +against Windows 9x, Windows ME servers. diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index 77da902d8f32..ec00d61d5308 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -23,6 +23,7 @@ #define CIFS_MOUNT_SERVER_INUM 4 /* inode numbers from uniqueid from server */ #define CIFS_MOUNT_DIRECT_IO 8 /* do not write nor read through page cache */ #define CIFS_MOUNT_NO_XATTR 0x10 /* if set - disable xattr support */ +#define CIFS_MOUNT_MAP_SPECIAL_CHR 0x20 /* remap illegal chars in filenames */ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index dd95c2bcbc25..b486ba738d95 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -212,6 +212,8 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 * inode_number, const struct nls_table *nls_codepage); +extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, + const struct nls_table * codepage); #endif /* CONFIG_CIFS_EXPERIMENTAL */ extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 814e709ca0ca..3d036bf689d8 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -72,6 +72,7 @@ struct smb_vol { unsigned no_xattr:1; /* set if xattr (EA) support should be disabled*/ unsigned server_ino:1; /* use inode numbers from server ie UniqueId */ unsigned direct_io:1; + unsigned remap:1; /* set to remap seven reserved chars in filenames */ unsigned int rsize; unsigned int wsize; unsigned int sockopt; @@ -771,6 +772,10 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) vol->noperm = 0; } else if (strnicmp(data, "noperm", 6) == 0) { vol->noperm = 1; + } else if (strnicmp(data, "mapchars", 8) == 0) { + vol->remap = 1; + } else if (strnicmp(data, "nomapchars", 10) == 0) { + vol->remap = 0; } else if (strnicmp(data, "setuids", 7) == 0) { vol->setuids = 1; } else if (strnicmp(data, "nosetuids", 9) == 0) { @@ -1421,6 +1426,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SET_UID; if(volume_info.server_ino) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_SERVER_INUM; + if(volume_info.remap) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MAP_SPECIAL_CHR; if(volume_info.no_xattr) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_NO_XATTR; if(volume_info.direct_io) { diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 7b38d3059a83..f2a026073b62 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -514,3 +514,72 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) printk( " | %s\n", debug_line); return; } + +#ifdef CONFIG_CIFS_EXPERIMENTAL +/* Windows maps these to the user defined 16 bit Unicode range since they are + reserved symbols (along with \ and /), otherwise illegal to store + in filenames in NTFS */ +#define UNI_ASTERIK cpu_to_le16('*' + 0xF000) +#define UNI_QUESTION cpu_to_le16('?' + 0xF000) +#define UNI_COLON cpu_to_le16(':' + 0xF000) +#define UNI_GRTRTHAN cpu_to_le16('>' + 0xF000) +#define UNI_LESSTHAN cpu_to_le16('<' + 0xF000) +#define UNI_PIPE cpu_to_le16('|' + 0xF000) +#define UNI_SLASH cpu_to_le16('\\' + 0xF000) + +/* Convert 16 bit Unicode pathname from wire format to string in current code + page. Conversion may involve remapping up the seven characters that are + only legal in POSIX-like OS (if they are present in the string). Path + names are little endian 16 bit Unicode on the wire */ +int +cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, + const struct nls_table * cp) +{ + int i,j,len; + wchar_t src_char; + + for(i = 0, j = 0; i < maxlen; i++) { + src_char = le16_to_cpu(source[i]); + switch (src_char) { + case 0: + goto cUCS_out; /* BB check this BB */ + case UNI_COLON: + target[j] = ':'; + break; + case UNI_ASTERIK: + target[j] = '*'; + break; + case UNI_QUESTION: + target[j] = '?'; + break; + case UNI_SLASH: + target[j] = '\\'; /* BB check this - is there risk here of converting path sep BB */ + break; + case UNI_PIPE: + target[j] = '|'; + break; + case UNI_GRTRTHAN: + target[j] = '>'; + break; + case UNI_LESSTHAN: + target[j] = '<'; + default: + len = cp->uni2char(src_char, &target[j], + NLS_MAX_CHARSET_SIZE); + if(len > 0) { + j += len; + continue; + } else { + target[j] = '?'; + } + } + j++; + /* check to make sure we do not overrun callers allocated temp buffer */ + if(j >= (2 * NAME_MAX)) + break; + } +cUCS_out: + target[j] = 0; + return j; +} +#endif /* CIFS_EXPERIMENTAL */ diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 07838a5ba3a1..4a33add24d53 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -600,7 +600,14 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, if(unicode) { /* BB fixme - test with long names */ /* Note converted filename can be longer than in unicode */ - pqst->len = cifs_strfromUCS_le((char *)pqst->name,(wchar_t *)filename,len/2,nlt); +#ifdef CONFIG_CIFS_EXPERIMENTAL + if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) + pqst->len = cifs_convertUCSpath((char *)pqst->name, + (__le16 *)filename, len/2, nlt); + else +#endif /* CIFS_EXPERIMENTAL */ + pqst->len = cifs_strfromUCS_le((char *)pqst->name, + (wchar_t *)filename,len/2,nlt); } else { pqst->name = filename; pqst->len = len; @@ -829,7 +836,11 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + smbCalcSize((struct smb_hdr *) cifsFile->srch_inf.ntwrk_buf_start); - tmp_buf = kmalloc(NAME_MAX+1,GFP_KERNEL); + /* To be safe - for UCS to UTF-8 with strings loaded + with the rare long characters alloc more to account for + such multibyte target UTF-8 characters. cifs_unicode.c, + which actually does the conversion, has the same limit */ + tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL); for(i=0;(i Date: Thu, 28 Apr 2005 22:41:05 -0700 Subject: [PATCH] cifs: remove a few redundant null pointer checks, and cleanup misc source formatting Mostly suggested by Jesper Juhl Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/dir.c | 83 ++++++++++---------- fs/cifs/smberr.h | 227 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 182 insertions(+), 128 deletions(-) (limited to 'fs') diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f54e1866f0f4..12ba81d7b07f 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -284,51 +284,48 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, /* mknod case - do not leave file open */ CIFSSMBClose(xid, pTcon, fileHandle); } else if(newinode) { - pCifsFile = (struct cifsFileInfo *) + pCifsFile = kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); - - if (pCifsFile) { - memset((char *)pCifsFile, 0, - sizeof (struct cifsFileInfo)); - pCifsFile->netfid = fileHandle; - pCifsFile->pid = current->tgid; - pCifsFile->pInode = newinode; - pCifsFile->invalidHandle = FALSE; - pCifsFile->closePend = FALSE; - init_MUTEX(&pCifsFile->fh_sem); - /* put the following in at open now */ - /* pCifsFile->pfile = file; */ - write_lock(&GlobalSMBSeslock); - list_add(&pCifsFile->tlist,&pTcon->openFileList); - pCifsInode = CIFS_I(newinode); - if(pCifsInode) { + + if(pCifsFile == NULL) + goto cifs_create_out; + memset((char *)pCifsFile, 0, + sizeof (struct cifsFileInfo)); + pCifsFile->netfid = fileHandle; + pCifsFile->pid = current->tgid; + pCifsFile->pInode = newinode; + pCifsFile->invalidHandle = FALSE; + pCifsFile->closePend = FALSE; + init_MUTEX(&pCifsFile->fh_sem); + /* set the following in open now + pCifsFile->pfile = file; */ + write_lock(&GlobalSMBSeslock); + list_add(&pCifsFile->tlist,&pTcon->openFileList); + pCifsInode = CIFS_I(newinode); + if(pCifsInode) { /* if readable file instance put first in list*/ - if (write_only == TRUE) { - list_add_tail(&pCifsFile->flist, - &pCifsInode->openFileList); - } else { - list_add(&pCifsFile->flist, - &pCifsInode->openFileList); - } - if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { - pCifsInode->clientCanCacheAll = TRUE; - pCifsInode->clientCanCacheRead = TRUE; - cFYI(1,("Exclusive Oplock granted on inode %p", - newinode)); - } else if((oplock & 0xF) == OPLOCK_READ) - pCifsInode->clientCanCacheRead = TRUE; + if (write_only == TRUE) { + list_add_tail(&pCifsFile->flist, + &pCifsInode->openFileList); + } else { + list_add(&pCifsFile->flist, + &pCifsInode->openFileList); } - write_unlock(&GlobalSMBSeslock); + if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { + pCifsInode->clientCanCacheAll = TRUE; + pCifsInode->clientCanCacheRead = TRUE; + cFYI(1,("Exclusive Oplock for inode %p", + newinode)); + } else if((oplock & 0xF) == OPLOCK_READ) + pCifsInode->clientCanCacheRead = TRUE; } + write_unlock(&GlobalSMBSeslock); } } - - if (buf) - kfree(buf); - if (full_path) - kfree(full_path); +cifs_create_out: + kfree(buf); + kfree(full_path); FreeXid(xid); - return rc; } @@ -375,10 +372,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev } } - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); - return rc; } @@ -447,8 +442,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name if file exists or not but no access BB */ } - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return ERR_PTR(rc); } @@ -478,8 +472,7 @@ cifs_dir_open(struct inode *inode, struct file *file) cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path)); - if (full_path) - kfree(full_path); + kfree(full_path); FreeXid(xid); return rc; } diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h index e21f1384661f..1b53dcd0f2eb 100644 --- a/fs/cifs/smberr.h +++ b/fs/cifs/smberr.h @@ -22,94 +22,155 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define SUCCESS 0 /* The request was successful. */ -#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ -#define ERRSRV 0x02 /* Error is generated by the file server daemon */ -#define ERRHRD 0x03 /* Error is a hardware error. */ -#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ +#define SUCCESS 0x00 /* The request was successful. */ +#define ERRDOS 0x01 /* Error is from the core DOS operating system set */ +#define ERRSRV 0x02 /* Error is generated by the file server daemon */ +#define ERRHRD 0x03 /* Error is a hardware error. */ +#define ERRCMD 0xFF /* Command was not in the "SMB" format. */ /* The following error codes may be generated with the SUCCESS error class.*/ -#define SUCCESS 0 /* The request was successful. */ +/*#define SUCCESS 0 The request was successful. */ /* The following error codes may be generated with the ERRDOS error class.*/ -#define ERRbadfunc 1 /* Invalid function. The server did not recognize or could not perform a system call generated by the server, e.g., set the DIRECTORY attribute on a data file, invalid seek mode. */ -#define ERRbadfile 2 /*File not found. The last component of a file's pathname could not be found. */ -#define ERRbadpath 3 /* Directory invalid. A directory component in a pathname could not be found. */ -#define ERRnofids 4 /* Too many open files. The server has no file handles available. */ -#define ERRnoaccess 5 /* Access denied, the client's context does not permit the requested function. This includes the following conditions: invalid rename command, write to Fid open for read only, read on Fid open for write only, attempt to delete a non-empty directory */ -#define ERRbadfid 6 /* Invalid file handle. The file handle specified was not recognized by the server. */ -#define ERRbadmcb 7 /* Memory control blocks destroyed. */ -#define ERRnomem 8 /* Insufficient server memory to perform the requested function. */ -#define ERRbadmem 9 /* Invalid memory block address. */ -#define ERRbadenv 10 /* Invalid environment. */ -#define ERRbadformat 11 /* Invalid format. */ -#define ERRbadaccess 12 /* Invalid open mode. */ -#define ERRbaddata 13 /* Invalid data (generated only by IOCTL calls within the server). */ -#define ERRbaddrive 15 /* Invalid drive specified. */ -#define ERRremcd 16 /* A Delete Directory request attempted to remove the server's current directory. */ -#define ERRdiffdevice 17 /* Not same device (e.g., a cross volume rename was attempted */ -#define ERRnofiles 18 /* A File Search command can find no more files matching the specified criteria. */ -#define ERRgeneral 31 -#define ERRbadshare 32 /* The sharing mode specified for an Open conflicts with existing FIDs on the file. */ -#define ERRlock 33 /* A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process. */ -#define ERRunsup 50 -#define ERRnosuchshare 67 -#define ERRfilexists 80 /* The file named in the request already exists. */ -#define ERRinvparm 87 -#define ERRdiskfull 112 -#define ERRinvname 123 -#define ERRinvlevel 124 -#define ERRdirnotempty 145 -#define ERRnotlocked 158 -#define ERRalreadyexists 183 -#define ERRbadpipe 230 -#define ERRpipebusy 231 -#define ERRpipeclosing 232 -#define ERRnotconnected 233 -#define ERRmoredata 234 -#define ERReasnotsupported 282 -#define ErrQuota 0x200 /* The operation would cause a quota limit to be exceeded. */ -#define ErrNotALink 0x201 /* A link operation was performed on a pathname that - was not a link. */ +#define ERRbadfunc 1 /* Invalid function. The server did not + recognize or could not perform a + system call generated by the server, + e.g., set the DIRECTORY attribute on + a data file, invalid seek mode. */ +#define ERRbadfile 2 /* File not found. The last component + of a file's pathname could not be + found. */ +#define ERRbadpath 3 /* Directory invalid. A directory + component in a pathname could not be + found. */ +#define ERRnofids 4 /* Too many open files. The server has + no file handles available. */ +#define ERRnoaccess 5 /* Access denied, the client's context + does not permit the requested + function. This includes the + following conditions: invalid rename + command, write to Fid open for read + only, read on Fid open for write + only, attempt to delete a non-empty + directory */ +#define ERRbadfid 6 /* Invalid file handle. The file handle + specified was not recognized by the + server. */ +#define ERRbadmcb 7 /* Memory control blocks destroyed. */ +#define ERRnomem 8 /* Insufficient server memory to + perform the requested function. */ +#define ERRbadmem 9 /* Invalid memory block address. */ +#define ERRbadenv 10 /* Invalid environment. */ +#define ERRbadformat 11 /* Invalid format. */ +#define ERRbadaccess 12 /* Invalid open mode. */ +#define ERRbaddata 13 /* Invalid data (generated only by + IOCTL calls within the server). */ +#define ERRbaddrive 15 /* Invalid drive specified. */ +#define ERRremcd 16 /* A Delete Directory request attempted + to remove the server's current + directory. */ +#define ERRdiffdevice 17 /* Not same device (e.g., a cross + volume rename was attempted */ +#define ERRnofiles 18 /* A File Search command can find no + more files matching the specified + criteria. */ +#define ERRgeneral 31 +#define ERRbadshare 32 /* The sharing mode specified for an + Open conflicts with existing FIDs on + the file. */ +#define ERRlock 33 /* A Lock request conflicted with an + existing lock or specified an + invalid mode, or an Unlock requested + attempted to remove a lock held by + another process. */ +#define ERRunsup 50 +#define ERRnosuchshare 67 +#define ERRfilexists 80 /* The file named in the request + already exists. */ +#define ERRinvparm 87 +#define ERRdiskfull 112 +#define ERRinvname 123 +#define ERRinvlevel 124 +#define ERRdirnotempty 145 +#define ERRnotlocked 158 +#define ERRalreadyexists 183 +#define ERRbadpipe 230 +#define ERRpipebusy 231 +#define ERRpipeclosing 232 +#define ERRnotconnected 233 +#define ERRmoredata 234 +#define ERReasnotsupported 282 +#define ErrQuota 0x200 /* The operation would cause a quota + limit to be exceeded. */ +#define ErrNotALink 0x201 /* A link operation was performed on a + pathname that was not a link. */ -/* Following error codes may be generated with the ERRSRV error -class.*/ +/* Following error codes may be generated with the ERRSRV error class.*/ -#define ERRerror 1 /* Non-specific error code. It is returned under the following conditions: resource other than disk space exhausted (e.g. TIDs), first SMB command was not negotiate, multiple negotiates attempted, and internal server error. */ -#define ERRbadpw 2 /* Bad password - name/password pair in a TreeConnect or Session Setup are invalid. */ -#define ERRbadtype 3 /* used for indicating DFS referral needed */ -#define ERRaccess 4 /* The client does not have the necessary access rights within the specified context for requested function. */ -#define ERRinvtid 5 /* The Tid specified in a command was invalid. */ -#define ERRinvnetname 6 /* Invalid network name in tree connect. */ -#define ERRinvdevice 7 /* Invalid device - printer request made to non-printer connection or non-printer request made to printer connection. */ -#define ERRqfull 49 /* Print queue full (files) -- returned by open print file. */ -#define ERRqtoobig 50 /* Print queue full -- no space. */ -#define ERRqeof 51 /* EOF on print queue dump */ -#define ERRinvpfid 52 /* Invalid print file FID. */ -#define ERRsmbcmd 64 /* The server did not recognize the command received. */ -#define ERRsrverror 65 /* The server encountered an internal error, e.g., system file unavailable. */ -#define ERRbadBID 66 /* (obsolete) */ -#define ERRfilespecs 67 /* The Fid and pathname parameters contained an invalid combination of values. */ -#define ERRbadLink 68 /* (obsolete) */ -#define ERRbadpermits 69 /* The access permissions specified for a file or directory are not a valid combination. */ -#define ERRbadPID 70 -#define ERRsetattrmode 71 /* attribute (mode) is invalid */ -#define ERRpaused 81 /* Server is paused */ -#define ERRmsgoff 82 /* reserved - messaging off */ -#define ERRnoroom 83 /* reserved - no room for message */ -#define ERRrmuns 87 /* reserved - too many remote names */ -#define ERRtimeout 88 /* operation timed out */ -#define ERRnoresource 89 /* No resources available for request */ -#define ERRtoomanyuids 90 /* Too many UIDs active on this session */ -#define ERRbaduid 91 /* The UID is not known as a valid user */ -#define ERRusempx 250 /* temporarily unable to use raw */ -#define ERRusestd 251 /* temporarily unable to use either raw or mpx */ -#define ERR_NOTIFY_ENUM_DIR 1024 -#define ERRaccountexpired 2239 -#define ERRbadclient 2240 -#define ERRbadLogonTime 2241 -#define ERRpasswordExpired 2242 -#define ERRnetlogonNotStarted 2455 -#define ERRnosupport 0xFFFF +#define ERRerror 1 /* Non-specific error code. It is + returned under the following + conditions: resource other than disk + space exhausted (e.g. TIDs), first + SMB command was not negotiate, + multiple negotiates attempted, and + internal server error. */ +#define ERRbadpw 2 /* Bad password - name/password pair in + a TreeConnect or Session Setup are + invalid. */ +#define ERRbadtype 3 /* used for indicating DFS referral + needed */ +#define ERRaccess 4 /* The client does not have the + necessary access rights within the + specified context for requested + function. */ +#define ERRinvtid 5 /* The Tid specified in a command was + invalid. */ +#define ERRinvnetname 6 /* Invalid network name in tree + connect. */ +#define ERRinvdevice 7 /* Invalid device - printer request + made to non-printer connection or + non-printer request made to printer + connection. */ +#define ERRqfull 49 /* Print queue full (files) -- returned + by open print file. */ +#define ERRqtoobig 50 /* Print queue full -- no space. */ +#define ERRqeof 51 /* EOF on print queue dump */ +#define ERRinvpfid 52 /* Invalid print file FID. */ +#define ERRsmbcmd 64 /* The server did not recognize the + command received. */ +#define ERRsrverror 65 /* The server encountered an internal + error, e.g., system file + unavailable. */ +#define ERRbadBID 66 /* (obsolete) */ +#define ERRfilespecs 67 /* The Fid and pathname parameters + contained an invalid combination of + values. */ +#define ERRbadLink 68 /* (obsolete) */ +#define ERRbadpermits 69 /* The access permissions specified for + a file or directory are not a valid + combination. */ +#define ERRbadPID 70 +#define ERRsetattrmode 71 /* attribute (mode) is invalid */ +#define ERRpaused 81 /* Server is paused */ +#define ERRmsgoff 82 /* reserved - messaging off */ +#define ERRnoroom 83 /* reserved - no room for message */ +#define ERRrmuns 87 /* reserved - too many remote names */ +#define ERRtimeout 88 /* operation timed out */ +#define ERRnoresource 89 /* No resources available for request + */ +#define ERRtoomanyuids 90 /* Too many UIDs active on this session + */ +#define ERRbaduid 91 /* The UID is not known as a valid user + */ +#define ERRusempx 250 /* temporarily unable to use raw */ +#define ERRusestd 251 /* temporarily unable to use either raw + or mpx */ +#define ERR_NOTIFY_ENUM_DIR 1024 +#define ERRaccountexpired 2239 +#define ERRbadclient 2240 +#define ERRbadLogonTime 2241 +#define ERRpasswordExpired 2242 +#define ERRnetlogonNotStarted 2455 +#define ERRnosupport 0xFFFF -- cgit v1.2.3 From 6c91d362f1e1ebbd4513adb68fc79d552c11e2c0 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:06 -0700 Subject: [PATCH] cifs: finish up of special character mapping capable unicode conversion routine part 2 of 3 Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifs_debug.c | 10 ++++--- fs/cifs/cifs_unicode.c | 4 +-- fs/cifs/misc.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 83 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index db28b561cd4b..e7bd93e6226d 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -29,6 +29,7 @@ #include "cifsglob.h" #include "cifsproto.h" #include "cifs_debug.h" +#include "cifsfs.h" void cifs_dump_mem(char *label, void *data, int length) @@ -78,8 +79,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, "Display Internal CIFS Data Structures for Debugging\n" "---------------------------------------------------\n"); buf += length; - - length = sprintf(buf, "Servers:\n"); + length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION); + buf += length; + length = sprintf(buf, "Servers:"); buf += length; i = 0; @@ -100,7 +102,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ses->server->secMode, atomic_read(&ses->server->inFlight)); - length = sprintf(buf, "\nMIDs: \n"); + length = sprintf(buf, "\nMIDs:\n"); buf += length; spin_lock(&GlobalMid_Lock); @@ -121,7 +123,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, sprintf(buf, "\n"); buf++; - length = sprintf(buf, "\nShares:\n"); + length = sprintf(buf, "Shares:"); buf += length; i = 0; diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index a17adf4cb9ba..99a096d3f84d 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -76,8 +76,8 @@ cifs_strtoUCS(wchar_t * to, const char *from, int len, charlen)); to[i] = cpu_to_le16(0x003f); /* a question mark */ charlen = 1; - } - to[i] = cpu_to_le16(to[i]); + } else + to[i] = cpu_to_le16(to[i]); } diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index f2a026073b62..6d7bb427e4fa 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -28,6 +28,7 @@ #include "cifs_debug.h" #include "smberr.h" #include "nterr.h" +#include "cifs_unicode.h" extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; @@ -515,7 +516,6 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) return; } -#ifdef CONFIG_CIFS_EXPERIMENTAL /* Windows maps these to the user defined 16 bit Unicode range since they are reserved symbols (along with \ and /), otherwise illegal to store in filenames in NTFS */ @@ -552,9 +552,12 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, case UNI_QUESTION: target[j] = '?'; break; - case UNI_SLASH: - target[j] = '\\'; /* BB check this - is there risk here of converting path sep BB */ - break; + /* BB We can not handle remapping slash until + all the calls to build_path_from_dentry + are modified, as they use slash as separator BB */ + /* case UNI_SLASH: + target[j] = '\\'; + break;*/ case UNI_PIPE: target[j] = '|'; break; @@ -582,4 +585,71 @@ cUCS_out: target[j] = 0; return j; } -#endif /* CIFS_EXPERIMENTAL */ + +/* Convert 16 bit Unicode pathname to wire format from string in current code + page. Conversion may involve remapping up the seven characters that are + only legal in POSIX-like OS (if they are present in the string). Path + names are little endian 16 bit Unicode on the wire */ +int +cifsConvertToUCS(__le16 * target, const char *source, int maxlen, + const struct nls_table * cp, int mapChars) +{ + int i,j,charlen; + int len_remaining = maxlen; + char src_char; + + if(!mapChars) + return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); + + for(i = 0, j = 0; i < maxlen; j++) { + src_char = source[i]; + switch (src_char) { + case 0: + goto ctoUCS_out; + case ':': + target[j] = cpu_to_le16(UNI_COLON); + break; + case '*': + target[j] = cpu_to_le16(UNI_ASTERIK); + break; + case '?': + target[j] = cpu_to_le16(UNI_QUESTION); + break; + case '<': + target[j] = cpu_to_le16(UNI_LESSTHAN); + break; + case '>': + target[j] = cpu_to_le16(UNI_GRTRTHAN); + break; + case '|': + target[j] = cpu_to_le16(UNI_PIPE); + break; + /* BB We can not handle remapping slash until + all the calls to build_path_from_dentry + are modified, as they use slash as separator BB */ + /* case '\\': + target[j] = cpu_to_le16(UNI_SLASH); + break;*/ + default: + charlen = cp->char2uni(source+i, + len_remaining, target+j); + /* if no match, use question mark, which + at least in some cases servers as wild card */ + if(charlen < 1) { + target[j] = cpu_to_le16(0x003f); + charlen = 1; + } + len_remaining -= charlen; + /* character may take more than one byte in the + the source string, but will take exactly two + bytes in the target string */ + i+= charlen; + continue; + } + i++; /* move to next char in source string */ + len_remaining--; + } + +ctoUCS_out: + return i; +} -- cgit v1.2.3 From 737b758c965a9b223ac1243ab38d9e507ac86c64 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:06 -0700 Subject: [PATCH] cifs: character mapping of special characters (part 3 of 3) Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 2 +- fs/cifs/README | 4 +- fs/cifs/TODO | 3 + fs/cifs/cifsfs.c | 4 +- fs/cifs/cifsproto.h | 103 ++++++++++++++---------- fs/cifs/cifssmb.c | 226 +++++++++++++++++++++++++--------------------------- fs/cifs/connect.c | 25 +++--- fs/cifs/dir.c | 108 ++++--------------------- fs/cifs/fcntl.c | 3 +- fs/cifs/file.c | 10 ++- fs/cifs/inode.c | 106 +++++++++++++++++------- fs/cifs/link.c | 18 ++++- fs/cifs/readdir.c | 22 +---- fs/cifs/xattr.c | 35 +++++--- 14 files changed, 337 insertions(+), 332 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 412b6d243d53..de8858028d64 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -9,7 +9,7 @@ POSIX ACL capability bit. Fix packet signing when multiuser mounting with different users from the same client to the same server. Fix oops in cifs_close. Add mount option for remapping reserved characters in filenames (also allow recognizing files with created by SFU which have any -of these seven reserved characters to be recognized). +of these seven reserved characters, except backslash, to be recognized). Version 1.31 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index 83e054576258..93900fc4adaa 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -376,8 +376,8 @@ A partial list of the supported mount options follows: attributes) to the server (default) e.g. via setfattr and getfattr utilities. nouser_xattr Do not allow getfattr/setfattr to get/set xattrs - mapchars Translate the seven reserved characters - *?<>|:\ + mapchars Translate six of the seven reserved characters (not backslash) + *?<>|: to the remap range (above 0xF000), which also allows the CIFS client to recognize files created with such characters by Windows's POSIX emulation. This can diff --git a/fs/cifs/TODO b/fs/cifs/TODO index a69227415a73..1e8490ed6948 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -67,6 +67,9 @@ q) implement support for security and trusted categories of xattrs r) Implement O_DIRECT flag on open (already supported on mount) +s) Allow remapping of last remaining character (\) to +0xF000 which +(this character is valid for POSIX but not for Windows) + KNOWN BUGS (updated April 3, 2005) ==================================== See http://bugzilla.samba.org - search on product "CifsVFS" for diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index ae48ef042977..3d5365b9f5ba 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -191,13 +191,13 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) #ifdef CONFIG_CIFS_EXPERIMENTAL /* BB we could add a second check for a QFS Unix capability bit */ if (pTcon->ses->capabilities & CAP_UNIX) - rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf, cifs_sb->local_nls); + rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); /* Only need to call the old QFSInfo if failed on newer one */ if(rc) #endif /* CIFS_EXPERIMENTAL */ - rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls); + rc = CIFSSMBQFSInfo(xid, pTcon, buf); /* int f_type; diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index b486ba738d95..0010511083fc 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -57,10 +57,11 @@ extern int decode_negTokenInit(unsigned char *security_blob, int length, extern int cifs_inet_pton(int, char * source, void *dst); extern int map_smb_to_linux_error(struct smb_hdr *smb); extern void header_assemble(struct smb_hdr *, char /* command */ , - const struct cifsTconInfo *, int - /* length of fixed section (word count) in two byte units */ + const struct cifsTconInfo *, int /* specifies length + of fixed section (word count) in two byte units */ ); -extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, struct cifsTconInfo *); +extern struct oplock_q_entry * AllocOplockQEntry(struct inode *, u16, + struct cifsTconInfo *); extern void DeleteOplockQEntry(struct oplock_q_entry *); extern struct timespec cifs_NTtimeToUnix(u64 /* utc nanoseconds since 1601 */ ); extern u64 cifs_UnixTimeToNT(struct timespec); @@ -88,7 +89,7 @@ extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, const char *searchName, const struct nls_table *nls_codepage, - __u16 *searchHandle, struct cifs_search_info * psrch_inf); + __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map); extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon, __u16 searchHandle, struct cifs_search_info * psrch_inf); @@ -99,42 +100,42 @@ extern int CIFSFindClose(const int, struct cifsTconInfo *tcon, extern int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_ALL_INFO * findData, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap); extern int CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_UNIX_BASIC_INFO * pFindData, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap); extern int CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, unsigned char **targetUNCs, unsigned int *number_of_UNC_in_array, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap); extern int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap); extern int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, - const char *old_path, const struct nls_table *nls_codepage, - unsigned int *pnum_referrals, unsigned char ** preferrals); + const char *old_path, + const struct nls_table *nls_codepage, + unsigned int *pnum_referrals, + unsigned char ** preferrals, + int remap); extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, - struct kstatfs *FSData, - const struct nls_table *nls_codepage); + struct kstatfs *FSData); extern int CIFSSMBQFSAttributeInfo(const int xid, - struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage); -extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage); -extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage); + struct cifsTconInfo *tcon); +extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon); +extern int CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon); extern int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, - struct kstatfs *FSData, const struct nls_table *nls_codepage); + struct kstatfs *FSData); extern int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, const FILE_BASIC_INFO * data, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_INFO * data, __u16 fid); #if 0 @@ -143,36 +144,49 @@ extern int CIFSSMBSetAttrLegacy(int xid, struct cifsTconInfo *tcon, const struct nls_table *nls_codepage); #endif /* possibly unneeded function */ extern int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, - const char *fileName, __u64 size,int setAllocationSizeFlag, - const struct nls_table *nls_codepage); + const char *fileName, __u64 size, + int setAllocationSizeFlag, + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, - __u64 size, __u16 fileHandle,__u32 opener_pid, int AllocSizeFlag); + __u64 size, __u16 fileHandle,__u32 opener_pid, + int AllocSizeFlag); extern int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *pTcon, char *full_path, __u64 mode, __u64 uid, - __u64 gid, dev_t dev, const struct nls_table *nls_codepage); + __u64 gid, dev_t dev, + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, const char *newName, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, - const char *name, const struct nls_table *nls_codepage); + const char *name, const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *name, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, - int netfid, char * target_name, const struct nls_table *nls_codepage); + int netfid, char * target_name, + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSUnixCreateSymLink(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, @@ -192,7 +206,7 @@ extern int CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int disposition, const int access_flags, const int omode, __u16 * netfid, int *pOplock, FILE_ALL_INFO *, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap); extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, const int smb_file_id); @@ -211,10 +225,13 @@ extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon, const char __user *buf,const int long_op); extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 * inode_number, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); +#endif /* CONFIG_CIFS_EXPERIMENTAL */ extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen, const struct nls_table * codepage); -#endif /* CONFIG_CIFS_EXPERIMENTAL */ +extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen, + const struct nls_table * cp, int mapChars); extern int CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, const __u16 netfid, const __u64 len, @@ -243,29 +260,31 @@ extern int CIFSSMBCopy(int xid, const char *fromName, const __u16 target_tid, const char *toName, const int flags, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, + int remap_special_chars); extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, - const int notify_subdirs,const __u16 netfid,__u32 filter, - const struct nls_table *nls_codepage); + const int notify_subdirs,const __u16 netfid, + __u32 filter, const struct nls_table *nls_codepage); extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char * EAData, - size_t bufsize, const struct nls_table *nls_codepage); + size_t bufsize, const struct nls_table *nls_codepage, + int remap_special_chars); extern ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, const unsigned char * searchName,const unsigned char * ea_name, unsigned char * ea_value, size_t buf_size, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, const char * ea_name, const void * ea_value, const __u16 ea_value_len, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char *acl_inf, const int buflen,const int acl_type, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *fileName, const char *local_acl, const int buflen, const int acl_type, - const struct nls_table *nls_codepage); + const struct nls_table *nls_codepage, int remap_special_chars); extern int CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon, const int netfid, __u64 * pExtAttrBits, __u64 *pMask); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 237e3bf94bfe..f7c4914c3dd9 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -538,8 +538,8 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) } int -CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, - const char *fileName, const struct nls_table *nls_codepage) +CIFSSMBDelFile(const int xid, struct cifsTconInfo *tcon, const char *fileName, + const struct nls_table *nls_codepage, int remap) { DELETE_FILE_REQ *pSMB = NULL; DELETE_FILE_RSP *pSMBr = NULL; @@ -555,9 +555,8 @@ DelFileRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->fileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -589,8 +588,8 @@ DelFileRetry: } int -CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, - const char *dirName, const struct nls_table *nls_codepage) +CIFSSMBRmDir(const int xid, struct cifsTconInfo *tcon, const char *dirName, + const struct nls_table *nls_codepage, int remap) { DELETE_DIRECTORY_REQ *pSMB = NULL; DELETE_DIRECTORY_RSP *pSMBr = NULL; @@ -606,9 +605,8 @@ RmDirRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, dirName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -639,7 +637,7 @@ RmDirRetry: int CIFSSMBMkDir(const int xid, struct cifsTconInfo *tcon, - const char *name, const struct nls_table *nls_codepage) + const char *name, const struct nls_table *nls_codepage, int remap) { int rc = 0; CREATE_DIRECTORY_REQ *pSMB = NULL; @@ -655,9 +653,8 @@ MkDirRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->DirName, name, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -690,7 +687,7 @@ CIFSSMBOpen(const int xid, struct cifsTconInfo *tcon, const char *fileName, const int openDisposition, const int access_flags, const int create_options, __u16 * netfid, int *pOplock, FILE_ALL_INFO * pfile_info, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { int rc = -EACCES; OPEN_REQ *pSMB = NULL; @@ -710,10 +707,8 @@ openRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { count = 1; /* account for one byte pad to word boundary */ name_len = - cifs_strtoUCS((wchar_t *) (pSMB->fileName + 1), - fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) (pSMB->fileName + 1), + fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->NameLength = cpu_to_le16(name_len); @@ -1108,7 +1103,7 @@ CIFSSMBClose(const int xid, struct cifsTconInfo *tcon, int smb_file_id) int CIFSSMBRename(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { int rc = 0; RENAME_REQ *pSMB = NULL; @@ -1131,18 +1126,16 @@ renameRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = - cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, PATH_MAX, - nls_codepage); + cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -1182,7 +1175,8 @@ renameRetry: } int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, - int netfid, char * target_name, const struct nls_table * nls_codepage) + int netfid, char * target_name, + const struct nls_table * nls_codepage, int remap) { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; @@ -1227,9 +1221,11 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, /* unicode only call */ if(target_name == NULL) { sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid); - len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, dummy_string, 24, nls_codepage); + len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, + dummy_string, 24, nls_codepage, remap); } else { - len_of_str = cifs_strtoUCS((wchar_t *) rename_info->target_name, target_name, PATH_MAX, nls_codepage); + len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name, + target_name, PATH_MAX, nls_codepage, remap); } rename_info->target_name_len = cpu_to_le32(2 * len_of_str); count = 12 /* sizeof(struct set_file_rename) */ + (2 * len_of_str) + 2; @@ -1263,7 +1259,7 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon, int CIFSSMBCopy(const int xid, struct cifsTconInfo *tcon, const char * fromName, const __u16 target_tid, const char *toName, const int flags, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { int rc = 0; COPY_REQ *pSMB = NULL; @@ -1285,18 +1281,16 @@ copyRetry: pSMB->Flags = cpu_to_le16(flags & COPY_TREE); if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->OldFileName, - fromName, - PATH_MAX /* find define for this maxpathcomponent */, - nls_codepage); + name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName, + fromName, PATH_MAX, nls_codepage, + remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; - name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, PATH_MAX, - nls_codepage); + name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -1425,7 +1419,7 @@ createSymLinkRetry: int CIFSUnixCreateHardLink(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -1444,9 +1438,8 @@ createHardLinkRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifs_strtoUCS((wchar_t *) pSMB->FileName, toName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -1468,9 +1461,8 @@ createHardLinkRetry: data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifs_strtoUCS((wchar_t *) data_offset, fromName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX, + nls_codepage, remap); name_len_target++; /* trailing null */ name_len_target *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -1512,7 +1504,7 @@ createHardLinkRetry: int CIFSCreateHardLink(const int xid, struct cifsTconInfo *tcon, const char *fromName, const char *toName, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { int rc = 0; NT_RENAME_REQ *pSMB = NULL; @@ -1539,17 +1531,15 @@ winCreateHardLinkRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->OldFileName, fromName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0; /* pad */ pSMB->OldFileName[name_len + 1] = 0x04; name_len2 = - cifs_strtoUCS((wchar_t *) & pSMB-> - OldFileName[name_len + 2], toName, PATH_MAX, - nls_codepage); + cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -1659,6 +1649,7 @@ querySymLinkRetry: name_len = UniStrnlen((wchar_t *) ((char *) &pSMBr->hdr.Protocol +data_offset), min_t(const int, buflen,count) / 2); + /* BB FIXME investigate remapping reserved chars here */ cifs_strfromUCS_le(symlinkinfo, (wchar_t *) ((char *)&pSMBr->hdr.Protocol + data_offset), @@ -1793,7 +1784,8 @@ static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace } /* Convert ACL from CIFS POSIX wire format to local Linux POSIX ACL xattr */ -static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,const int acl_type,const int size_of_data_area) +static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen, + const int acl_type,const int size_of_data_area) { int size = 0; int i; @@ -1912,7 +1904,7 @@ int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char *acl_inf, const int buflen, const int acl_type, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { /* SMB_QUERY_POSIX_ACL */ TRANSACTION2_QPI_REQ *pSMB = NULL; @@ -1932,8 +1924,8 @@ queryAclRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->FileName[name_len] = 0; @@ -1997,8 +1989,9 @@ queryAclRetry: int CIFSSMBSetPosixACL(const int xid, struct cifsTconInfo *tcon, const unsigned char *fileName, - const char *local_acl, const int buflen, const int acl_type, - const struct nls_table *nls_codepage) + const char *local_acl, const int buflen, + const int acl_type, + const struct nls_table *nls_codepage, int remap) { struct smb_com_transaction2_spi_req *pSMB = NULL; struct smb_com_transaction2_spi_rsp *pSMBr = NULL; @@ -2016,8 +2009,8 @@ setAclRetry: return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2161,7 +2154,7 @@ int CIFSSMBQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_ALL_INFO * pFindData, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { /* level 263 SMB_QUERY_FILE_ALL_INFO */ TRANSACTION2_QPI_REQ *pSMB = NULL; @@ -2180,9 +2173,8 @@ QPathInfoRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2243,7 +2235,7 @@ int CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, FILE_UNIX_BASIC_INFO * pFindData, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { /* SMB_QUERY_FILE_UNIX_BASIC */ TRANSACTION2_QPI_REQ *pSMB = NULL; @@ -2262,9 +2254,8 @@ UnixQPathInfoRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2344,7 +2335,7 @@ findUniqueRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX + cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX /* find define for this maxpathcomponent */ , nls_codepage); name_len++; /* trailing null */ @@ -2408,7 +2399,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, const char *searchName, const struct nls_table *nls_codepage, __u16 * pnetfid, - struct cifs_search_info * psrch_inf) + struct cifs_search_info * psrch_inf, int remap) { /* level 257 SMB_ */ TRANSACTION2_FFIRST_REQ *pSMB = NULL; @@ -2419,7 +2410,7 @@ CIFSFindFirst(const int xid, struct cifsTconInfo *tcon, int name_len; __u16 params, byte_count; - cFYI(1, ("In FindFirst")); + cFYI(1, ("In FindFirst for %s",searchName)); findFirstRetry: rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, @@ -2429,12 +2420,20 @@ findFirstRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName,searchName, - PATH_MAX, nls_codepage); - name_len++; /* trailing null */ + cifsConvertToUCS((__u16 *) pSMB->FileName,searchName, + PATH_MAX, nls_codepage, remap); + /* We can not add the asterik earlier in case + it got remapped to 0xF03A as if it were part of the + directory name instead of a wildcard */ name_len *= 2; + pSMB->FileName[name_len] = '\\'; + pSMB->FileName[name_len+1] = 0; + pSMB->FileName[name_len+2] = '*'; + pSMB->FileName[name_len+3] = 0; + name_len += 4; /* now the trailing null */ pSMB->FileName[name_len] = 0; /* null terminate just in case */ pSMB->FileName[name_len+1] = 0; + name_len += 2; } else { /* BB add check for overrun of SMB buf BB */ name_len = strnlen(searchName, PATH_MAX); name_len++; /* trailing null */ @@ -2691,7 +2690,7 @@ int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, __u64 * inode_number, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { int rc = 0; TRANSACTION2_QPI_REQ *pSMB = NULL; @@ -2712,8 +2711,8 @@ GetInodeNumberRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, - PATH_MAX,nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + PATH_MAX,nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2787,7 +2786,7 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses, const unsigned char *searchName, unsigned char **targetUNCs, unsigned int *number_of_UNC_in_array, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { /* TRANS2_GET_DFS_REFERRAL */ TRANSACTION2_GET_DFS_REFER_REQ *pSMB = NULL; @@ -2823,10 +2822,8 @@ getDFSRetry: if (ses->capabilities & CAP_UNICODE) { pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; name_len = - cifs_strtoUCS((wchar_t *) pSMB->RequestFileName, - searchName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->RequestFileName, + searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2954,8 +2951,7 @@ GetDFSRefExit: } int -CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, - struct kstatfs *FSData, const struct nls_table *nls_codepage) +CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon, struct kstatfs *FSData) { /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ TRANSACTION2_QFSI_REQ *pSMB = NULL; @@ -3038,8 +3034,7 @@ QFSInfoRetry: } int -CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage) +CIFSSMBQFSAttributeInfo(const int xid, struct cifsTconInfo *tcon) { /* level 0x105 SMB_QUERY_FILE_SYSTEM_INFO */ TRANSACTION2_QFSI_REQ *pSMB = NULL; @@ -3107,8 +3102,7 @@ QFSAttributeRetry: } int -CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage) +CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon) { /* level 0x104 SMB_QUERY_FILE_SYSTEM_INFO */ TRANSACTION2_QFSI_REQ *pSMB = NULL; @@ -3161,8 +3155,8 @@ QFSDeviceRetry: else { __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); response_data = - (FILE_SYSTEM_DEVICE_INFO - *) (((char *) &pSMBr->hdr.Protocol) + + (FILE_SYSTEM_DEVICE_INFO *) + (((char *) &pSMBr->hdr.Protocol) + data_offset); memcpy(&tcon->fsDevInfo, response_data, sizeof (FILE_SYSTEM_DEVICE_INFO)); @@ -3177,8 +3171,7 @@ QFSDeviceRetry: } int -CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon, - const struct nls_table *nls_codepage) +CIFSSMBQFSUnixInfo(const int xid, struct cifsTconInfo *tcon) { /* level 0x200 SMB_QUERY_CIFS_UNIX_INFO */ TRANSACTION2_QFSI_REQ *pSMB = NULL; @@ -3249,7 +3242,7 @@ QFSUnixRetry: int CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon, - struct kstatfs *FSData, const struct nls_table *nls_codepage) + struct kstatfs *FSData) { /* level 0x201 SMB_QUERY_CIFS_POSIX_INFO */ TRANSACTION2_QFSI_REQ *pSMB = NULL; @@ -3341,7 +3334,8 @@ QFSPosixRetry: int CIFSSMBSetEOF(const int xid, struct cifsTconInfo *tcon, const char *fileName, - __u64 size, int SetAllocation, const struct nls_table *nls_codepage) + __u64 size, int SetAllocation, + const struct nls_table *nls_codepage, int remap) { struct smb_com_transaction2_spi_req *pSMB = NULL; struct smb_com_transaction2_spi_rsp *pSMBr = NULL; @@ -3360,9 +3354,8 @@ SetEOFRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3595,7 +3588,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I int CIFSSMBSetTimes(const int xid, struct cifsTconInfo *tcon, const char *fileName, const FILE_BASIC_INFO * data, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -3615,9 +3608,8 @@ SetTimesRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3697,7 +3689,7 @@ SetAttrLgcyRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->fileName, fileName, + ConvertToUCS((wchar_t *) pSMB->fileName, fileName, PATH_MAX, nls_codepage); name_len++; /* trailing null */ name_len *= 2; @@ -3727,8 +3719,9 @@ SetAttrLgcyRetry: int CIFSSMBUnixSetPerms(const int xid, struct cifsTconInfo *tcon, - char *fileName, __u64 mode, __u64 uid, __u64 gid, - dev_t device, const struct nls_table *nls_codepage) + char *fileName, __u64 mode, __u64 uid, __u64 gid, + dev_t device, const struct nls_table *nls_codepage, + int remap) { TRANSACTION2_SPI_REQ *pSMB = NULL; TRANSACTION2_SPI_RSP *pSMBr = NULL; @@ -3747,9 +3740,8 @@ setPermsRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3872,7 +3864,7 @@ ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, const unsigned char *searchName, char * EAData, size_t buf_size, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { /* BB assumes one setup word */ TRANSACTION2_QPI_REQ *pSMB = NULL; @@ -3893,9 +3885,8 @@ QAllEAsRetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -4017,7 +4008,7 @@ QAllEAsRetry: ssize_t CIFSSMBQueryEA(const int xid,struct cifsTconInfo * tcon, const unsigned char * searchName,const unsigned char * ea_name, unsigned char * ea_value, size_t buf_size, - const struct nls_table *nls_codepage) + const struct nls_table *nls_codepage, int remap) { TRANSACTION2_QPI_REQ *pSMB = NULL; TRANSACTION2_QPI_RSP *pSMBr = NULL; @@ -4037,9 +4028,8 @@ QEARetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -4165,7 +4155,8 @@ QEARetry: int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, const char *fileName, const char * ea_name, const void * ea_value, - const __u16 ea_value_len, const struct nls_table *nls_codepage) + const __u16 ea_value_len, const struct nls_table *nls_codepage, + int remap) { struct smb_com_transaction2_spi_req *pSMB = NULL; struct smb_com_transaction2_spi_rsp *pSMBr = NULL; @@ -4184,9 +4175,8 @@ SetEARetry: if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUCS((wchar_t *) pSMB->FileName, fileName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifsConvertToUCS((__u16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 3d036bf689d8..1f22b85324cf 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -924,14 +924,15 @@ find_unc(__be32 new_target_ip_addr, char *uncName, char *userName) int connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, - const char *old_path, const struct nls_table *nls_codepage) + const char *old_path, const struct nls_table *nls_codepage, + int remap) { unsigned char *referrals = NULL; unsigned int num_referrals; int rc = 0; rc = get_dfs_path(xid, pSesInfo,old_path, nls_codepage, - &num_referrals, &referrals); + &num_referrals, &referrals, remap); /* BB Add in code to: if valid refrl, if not ip address contact the helper that resolves tcp names, mount to it, try to @@ -946,7 +947,8 @@ connect_to_dfs_path(int xid, struct cifsSesInfo *pSesInfo, int get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, const char *old_path, const struct nls_table *nls_codepage, - unsigned int *pnum_referrals, unsigned char ** preferrals) + unsigned int *pnum_referrals, + unsigned char ** preferrals, int remap) { char *temp_unc; int rc = 0; @@ -971,7 +973,7 @@ get_dfs_path(int xid, struct cifsSesInfo *pSesInfo, } if (rc == 0) rc = CIFSGetDFSRefer(xid, pSesInfo, old_path, preferrals, - pnum_referrals, nls_codepage); + pnum_referrals, nls_codepage, remap); return rc; } @@ -1456,11 +1458,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, if ((strchr(volume_info.UNC + 3, '\\') == NULL) && (strchr(volume_info.UNC + 3, '/') == NULL)) { - rc = connect_to_dfs_path(xid, - pSesInfo, - "", - cifs_sb-> - local_nls); + rc = connect_to_dfs_path(xid, pSesInfo, + "", cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if(volume_info.UNC) kfree(volume_info.UNC); FreeXid(xid); @@ -1523,10 +1524,10 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, tcon->ses = pSesInfo; /* do not care if following two calls succeed - informational only */ - CIFSSMBQFSDeviceInfo(xid, tcon, cifs_sb->local_nls); - CIFSSMBQFSAttributeInfo(xid, tcon, cifs_sb->local_nls); + CIFSSMBQFSDeviceInfo(xid, tcon); + CIFSSMBQFSAttributeInfo(xid, tcon); if (tcon->ses->capabilities & CAP_UNIX) { - if(!CIFSSMBQFSUnixInfo(xid, tcon, cifs_sb->local_nls)) { + if(!CIFSSMBQFSUnixInfo(xid, tcon)) { if(!volume_info.no_psx_acl) { if(CIFS_UNIX_POSIX_ACL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 12ba81d7b07f..e3137aa48cdd 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -101,68 +101,15 @@ cifs_bp_rename_retry: return full_path; } -/* Note: caller must free return buffer */ -char * -build_wildcard_path_from_dentry(struct dentry *direntry) +/* char * build_wildcard_path_from_dentry(struct dentry *direntry) { - struct dentry *temp; - int namelen = 0; - char *full_path; - - if(direntry == NULL) - return NULL; /* not much we can do if dentry is freed and - we need to reopen the file after it was closed implicitly - when the server crashed */ - -cifs_bwp_rename_retry: - for (temp = direntry; !IS_ROOT(temp);) { - namelen += (1 + temp->d_name.len); - temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); - return NULL; - } - } - - full_path = kmalloc(namelen+3, GFP_KERNEL); if(full_path == NULL) return full_path; full_path[namelen] = '\\'; full_path[namelen+1] = '*'; - full_path[namelen+2] = 0; /* trailing null */ - - for (temp = direntry; !IS_ROOT(temp);) { - namelen -= 1 + temp->d_name.len; - if (namelen < 0) { - break; - } else { - full_path[namelen] = '\\'; - strncpy(full_path + namelen + 1, temp->d_name.name, - temp->d_name.len); - cFYI(0, (" name: %s ", full_path + namelen)); - } - temp = temp->d_parent; - if(temp == NULL) { - cERROR(1,("corrupt dentry")); - kfree(full_path); - return NULL; - } - } - if (namelen != 0) { - cERROR(1, - ("We did not end path lookup where we expected namelen is %d", - namelen)); - /* presumably this is only possible if we were racing with a rename - of one of the parent directories (we can not lock the dentries - above us to prevent this, but retrying should be harmless) */ - kfree(full_path); - namelen = 0; - goto cifs_bwp_rename_retry; - } - - return full_path; -} + full_path[namelen+2] = 0; +BB remove above eight lines BB */ /* Inode operations in similar order to how they appear in the Linux file fs.h */ @@ -235,7 +182,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, - &fileHandle, &oplock, buf, cifs_sb->local_nls); + &fileHandle, &oplock, buf, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { cFYI(1, ("cifs_create returned 0x%x ", rc)); } else { @@ -248,13 +196,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (__u64)current->euid, (__u64)current->egid, 0 /* dev */, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)-1, (__u64)-1, 0 /* dev */, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { /* BB implement via Windows security descriptors */ @@ -356,11 +308,15 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, dev_t dev if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,(__u64)current->euid,(__u64)current->egid, - device_number, cifs_sb->local_nls); + device_number, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)-1, (__u64)-1, - device_number, cifs_sb->local_nls); + device_number, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } if(!rc) { @@ -447,36 +403,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name return ERR_PTR(rc); } -int -cifs_dir_open(struct inode *inode, struct file *file) -{ /* NB: currently unused since searches are opened in readdir */ - int rc = 0; - int xid; - struct cifs_sb_info *cifs_sb; - struct cifsTconInfo *pTcon; - char *full_path = NULL; - - xid = GetXid(); - - cifs_sb = CIFS_SB(inode->i_sb); - pTcon = cifs_sb->tcon; - - if(file->f_dentry) { - down(&file->f_dentry->d_sb->s_vfs_rename_sem); - full_path = build_wildcard_path_from_dentry(file->f_dentry); - up(&file->f_dentry->d_sb->s_vfs_rename_sem); - } else { - FreeXid(xid); - return -EIO; - } - - cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path)); - - kfree(full_path); - FreeXid(xid); - return rc; -} - static int cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) { diff --git a/fs/cifs/fcntl.c b/fs/cifs/fcntl.c index 9d24c40f1967..7d2a9202c39a 100644 --- a/fs/cifs/fcntl.c +++ b/fs/cifs/fcntl.c @@ -92,7 +92,8 @@ int cifs_dir_notify(struct file * file, unsigned long arg) cERROR(1,("cifs dir notify on file %s with arg 0x%lx",full_path,arg)); /* BB removeme BB */ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ | SYNCHRONIZE, 0 /* create options */, - &netfid, &oplock,NULL, cifs_sb->local_nls); + &netfid, &oplock,NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); /* BB fixme - add this handle to a notify handle list */ if(rc) { cERROR(1,("Could not open directory for notify")); /* BB remove BB */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 9c7755053099..1df26ddf68b1 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -254,7 +254,8 @@ int cifs_open(struct inode *inode, struct file *file) } rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, - cifs_sb->local_nls); + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags + & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { cFYI(1, ("cifs_open returned 0x%x ", rc)); goto out; @@ -287,7 +288,9 @@ int cifs_open(struct inode *inode, struct file *file) CIFSSMBUnixSetPerms(xid, pTcon, full_path, inode->i_mode, (__u64)-1, (__u64)-1, 0 /* dev */, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { /* BB implement via Windows security descriptors eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, @@ -387,7 +390,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, } */ rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, NULL, - cifs_sb->local_nls); + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { up(&pCifsFile->fh_sem); cFYI(1, ("cifs_open returned 0x%x ", rc)); diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d73b0aa86775..670947288262 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -44,7 +44,8 @@ int cifs_get_inode_info_unix(struct inode **pinode, cFYI(1, (" Getting info on %s ", search_path)); /* could have done a find first instead but this returns more info */ rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData, - cifs_sb->local_nls); + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); /* dump_mem("\nUnixQPathInfo return data", &findData, sizeof(findData)); */ if (rc) { @@ -63,7 +64,9 @@ int cifs_get_inode_info_unix(struct inode **pinode, strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ @@ -210,7 +213,8 @@ int cifs_get_inode_info(struct inode **pinode, pfindData = (FILE_ALL_INFO *)buf; /* could do find first instead but this returns more info */ rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData, - cifs_sb->local_nls); + cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } /* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */ if (rc) { @@ -230,7 +234,9 @@ int cifs_get_inode_info(struct inode **pinode, strncat(tmp_path, search_path, MAX_PATHCONF); rc = connect_to_dfs_path(xid, pTcon->ses, /* treename + */ tmp_path, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); kfree(tmp_path); /* BB fix up inode etc. */ } else if (rc) { @@ -268,7 +274,9 @@ int cifs_get_inode_info(struct inode **pinode, rc1 = CIFSGetSrvInodeNumber(xid, pTcon, search_path, &inode_num, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if(rc1) { cFYI(1,("GetSrvInodeNum rc %d", rc1)); /* BB EOPNOSUPP disable SERVER_INUM? */ @@ -410,7 +418,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) FreeXid(xid); return -ENOMEM; } - rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls); + rc = CIFSSMBDelFile(xid, pTcon, full_path, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { direntry->d_inode->i_nlink--; @@ -422,10 +431,14 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, DELETE, CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, - &netfid, &oplock, NULL, cifs_sb->local_nls); + &netfid, &oplock, NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); CIFSSMBClose(xid, pTcon, netfid); direntry->d_inode->i_nlink--; } @@ -439,7 +452,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) if (!(pTcon->ses->flags & CIFS_SES_NT4)) rc = CIFSSMBSetTimes(xid, pTcon, full_path, pinfo_buf, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); else rc = -EOPNOTSUPP; @@ -461,7 +476,9 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) FILE_OPEN, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, 0, &netfid, &oplock, NULL, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { rc = CIFSSMBSetFileTimes(xid, pTcon, pinfo_buf, @@ -472,8 +489,10 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) kfree(pinfo_buf); } if (rc==0) { - rc = CIFSSMBDelFile(xid, pTcon, full_path, - cifs_sb->local_nls); + rc = CIFSSMBDelFile(xid, pTcon, full_path, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { direntry->d_inode->i_nlink--; } else if (rc == -ETXTBSY) { @@ -485,11 +504,15 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry) CREATE_NOT_DIR | CREATE_DELETE_ON_CLOSE, &netfid, &oplock, NULL, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { CIFSSMBRenameOpenFile(xid, pTcon, netfid, NULL, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); CIFSSMBClose(xid, pTcon, netfid); direntry->d_inode->i_nlink--; } @@ -534,7 +557,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) return -ENOMEM; } /* BB add setting the equivalent of mode via CreateX w/ACLs */ - rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls); + rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { cFYI(1, ("cifs_mkdir returned 0x%x ", rc)); d_drop(direntry); @@ -558,12 +582,16 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) (__u64)current->euid, (__u64)current->egid, 0 /* dev_t */, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, (__u64)-1, (__u64)-1, 0 /* dev_t */, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } else { /* BB to be implemented via Windows secrty descriptors @@ -600,7 +628,8 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) return -ENOMEM; } - rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls); + rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { inode->i_nlink--; @@ -653,7 +682,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, } rc = CIFSSMBRename(xid, pTcon, fromName, toName, - cifs_sb_source->local_nls); + cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == -EEXIST) { /* check if they are the same file because rename of hardlinked files is a noop */ @@ -665,11 +696,16 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, if (info_buf_source != NULL) { info_buf_target = info_buf_source + 1; rc = CIFSSMBUnixQPathInfo(xid, pTcon, fromName, - info_buf_source, cifs_sb_source->local_nls); + info_buf_source, cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc == 0) { rc = CIFSSMBUnixQPathInfo(xid, pTcon, toName, info_buf_target, - cifs_sb_target->local_nls); + cifs_sb_target->local_nls, + /* remap based on source sb */ + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); } if ((rc == 0) && (info_buf_source->UniqueId == @@ -685,7 +721,9 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, cifs_unlink(target_inode, target_direntry); rc = CIFSSMBRename(xid, pTcon, fromName, toName, - cifs_sb_source->local_nls); + cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags + & CIFS_MOUNT_MAP_SPECIAL_CHR); } kfree(info_buf_source); } /* if we can not get memory just leave rc as EEXIST */ @@ -705,10 +743,14 @@ int cifs_rename(struct inode *source_inode, struct dentry *source_direntry, might not right be right access to request */ rc = CIFSSMBOpen(xid, pTcon, fromName, FILE_OPEN, GENERIC_READ, CREATE_NOT_DIR, &netfid, &oplock, NULL, - cifs_sb_source->local_nls); + cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { CIFSSMBRenameOpenFile(xid, pTcon, netfid, toName, - cifs_sb_source->local_nls); + cifs_sb_source->local_nls, + cifs_sb_source->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); CIFSSMBClose(xid, pTcon, netfid); } } @@ -962,7 +1004,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) it by handle */ rc = CIFSSMBSetEOF(xid, pTcon, full_path, attrs->ia_size, FALSE, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1, (" SetEOF by path (setattrs) rc = %d", rc)); } @@ -999,7 +1043,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && (attrs->ia_valid & (ATTR_MODE | ATTR_GID | ATTR_UID))) rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, uid, gid, - 0 /* dev_t */, cifs_sb->local_nls); + 0 /* dev_t */, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); else if (attrs->ia_valid & ATTR_MODE) { if ((mode & S_IWUGO) == 0) /* not writeable */ { if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) @@ -1048,7 +1094,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) via Handle (SetFileInfo) instead of by path */ if (!(pTcon->ses->flags & CIFS_SES_NT4)) rc = CIFSSMBSetTimes(xid, pTcon, full_path, &time_buf, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); else rc = -EOPNOTSUPP; @@ -1063,7 +1111,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, &netfid, &oplock, - NULL, cifs_sb->local_nls); + NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc==0) { rc = CIFSSMBSetFileTimes(xid, pTcon, &time_buf, netfid); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 1455810ba1cb..bde0fabfece0 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -59,10 +59,14 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode, if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX) rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb_target->local_nls); + cifs_sb_target->local_nls, + cifs_sb_target->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); else { rc = CIFSCreateHardLink(xid, pTcon, fromName, toName, - cifs_sb_target->local_nls); + cifs_sb_target->local_nls, + cifs_sb_target->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if(rc == -EIO) rc = -EOPNOTSUPP; } @@ -260,7 +264,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) cifs_sb->local_nls); else { rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ, - OPEN_REPARSE_POINT,&fid, &oplock, NULL, cifs_sb->local_nls); + OPEN_REPARSE_POINT,&fid, &oplock, NULL, + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if(!rc) { rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path, tmpbuffer, @@ -279,7 +286,10 @@ cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen) strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE); strncat(tmp_path, full_path, MAX_PATHCONF); rc = get_dfs_path(xid, pTcon->ses, tmp_path, - cifs_sb->local_nls, &num_referrals, &referrals); + cifs_sb->local_nls, + &num_referrals, &referrals, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1,("Get DFS for %s rc = %d ",tmp_path, rc)); if((num_referrals == 0) && (rc == 0)) rc = -EACCES; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 4a33add24d53..7ca876b6f2ab 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -314,7 +314,7 @@ static int initiate_cifs_search(const int xid, struct file *file) return -EINVAL; down(&file->f_dentry->d_sb->s_vfs_rename_sem); - full_path = build_wildcard_path_from_dentry(file->f_dentry); + full_path = build_path_from_dentry(file->f_dentry); up(&file->f_dentry->d_sb->s_vfs_rename_sem); if(full_path == NULL) { @@ -333,8 +333,9 @@ ffirst_retry: cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; } - rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, - &cifsFile->netfid, &cifsFile->srch_inf); + rc = CIFSFindFirst(xid, pTcon,full_path,cifs_sb->local_nls, + &cifsFile->netfid, &cifsFile->srch_inf, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if(rc == 0) cifsFile->invalidHandle = FALSE; if((rc == -EOPNOTSUPP) && @@ -600,12 +601,10 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst, if(unicode) { /* BB fixme - test with long names */ /* Note converted filename can be longer than in unicode */ -#ifdef CONFIG_CIFS_EXPERIMENTAL if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) pqst->len = cifs_convertUCSpath((char *)pqst->name, (__le16 *)filename, len/2, nlt); else -#endif /* CIFS_EXPERIMENTAL */ pqst->len = cifs_strfromUCS_le((char *)pqst->name, (wchar_t *)filename,len/2,nlt); } else { @@ -849,19 +848,6 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) break; } - /* BB FIXME - need to enable the below code BB */ - - /* if((!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) || - (cifsFile->srch_inf.info_level != - something that supports server inodes)) { - create dentry - create inode - fill in inode new_inode (getting local i_ino) - } - also create local inode for performance reasons (so we - have a cache of inode metadata) unless this new mount - parm says otherwise */ - rc = cifs_filldir(current_entry, file, filldir, direntry,tmp_buf); file->f_pos++; diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 9a41bee11c5a..c1e02eff1d25 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -83,7 +83,8 @@ int cifs_removexattr(struct dentry * direntry, const char * ea_name) ea_name+=5; /* skip past user. prefix */ rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,NULL, - (__u16)0, cifs_sb->local_nls); + (__u16)0, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } remove_ea_exit: if (full_path) @@ -147,14 +148,16 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, } ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, - (__u16)value_size, cifs_sb->local_nls); + (__u16)value_size, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; ea_name += 4; /* skip past os2. prefix */ rc = CIFSSMBSetEA(xid,pTcon,full_path,ea_name,ea_value, - (__u16)value_size, cifs_sb->local_nls); + (__u16)value_size, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else { int temp; temp = strncmp(ea_name,POSIX_ACL_XATTR_ACCESS, @@ -164,7 +167,9 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, ea_value, (const int)value_size, - ACL_TYPE_ACCESS,cifs_sb->local_nls); + ACL_TYPE_ACCESS,cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1,("set POSIX ACL rc %d",rc)); #else cFYI(1,("set POSIX ACL not supported")); @@ -174,7 +179,9 @@ int cifs_setxattr(struct dentry * direntry, const char * ea_name, if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBSetPosixACL(xid, pTcon,full_path, ea_value, (const int)value_size, - ACL_TYPE_DEFAULT, cifs_sb->local_nls); + ACL_TYPE_DEFAULT, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); cFYI(1,("set POSIX default ACL rc %d",rc)); #else cFYI(1,("set default POSIX ACL not supported")); @@ -240,20 +247,24 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, } /* BB add else when above is implemented */ ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, - buf_size, cifs_sb->local_nls); + buf_size, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else if(strncmp(ea_name, CIFS_XATTR_OS2_PREFIX,4) == 0) { if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; ea_name += 4; /* skip past os2. prefix */ rc = CIFSSMBQueryEA(xid,pTcon,full_path,ea_name,ea_value, - buf_size, cifs_sb->local_nls); + buf_size, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else if(strncmp(ea_name,POSIX_ACL_XATTR_ACCESS,strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { #ifdef CONFIG_CIFS_POSIX if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, ea_value, buf_size, ACL_TYPE_ACCESS, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); #else cFYI(1,("query POSIX ACL not supported yet")); #endif /* CONFIG_CIFS_POSIX */ @@ -262,7 +273,9 @@ ssize_t cifs_getxattr(struct dentry * direntry, const char * ea_name, if(sb->s_flags & MS_POSIXACL) rc = CIFSSMBGetPosixACL(xid, pTcon, full_path, ea_value, buf_size, ACL_TYPE_DEFAULT, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); #else cFYI(1,("query POSIX default ACL not supported yet")); #endif @@ -328,7 +341,9 @@ ssize_t cifs_listxattr(struct dentry * direntry, char * data, size_t buf_size) search server for EAs or streams to returns as xattrs */ rc = CIFSSMBQAllEAs(xid,pTcon,full_path,data,buf_size, - cifs_sb->local_nls); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); if (full_path) kfree(full_path); -- cgit v1.2.3 From d0724714fd49aeec1383b94807174de7e96021bf Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:06 -0700 Subject: [PATCH] cifs: Fix PPC64 compile error .. and do not double endian convert the special characters whem mounted with mapchars mount parm. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/misc.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 6d7bb427e4fa..75fd3bd6e233 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -519,13 +519,13 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) /* Windows maps these to the user defined 16 bit Unicode range since they are reserved symbols (along with \ and /), otherwise illegal to store in filenames in NTFS */ -#define UNI_ASTERIK cpu_to_le16('*' + 0xF000) -#define UNI_QUESTION cpu_to_le16('?' + 0xF000) -#define UNI_COLON cpu_to_le16(':' + 0xF000) -#define UNI_GRTRTHAN cpu_to_le16('>' + 0xF000) -#define UNI_LESSTHAN cpu_to_le16('<' + 0xF000) -#define UNI_PIPE cpu_to_le16('|' + 0xF000) -#define UNI_SLASH cpu_to_le16('\\' + 0xF000) +#define UNI_ASTERIK (__u16) ('*' + 0xF000) +#define UNI_QUESTION (__u16) ('?' + 0xF000) +#define UNI_COLON (__u16) (':' + 0xF000) +#define UNI_GRTRTHAN (__u16) ('>' + 0xF000) +#define UNI_LESSTHAN (__u16) ('<' + 0xF000) +#define UNI_PIPE (__u16) ('|' + 0xF000) +#define UNI_SLASH (__u16) ('\\' + 0xF000) /* Convert 16 bit Unicode pathname from wire format to string in current code page. Conversion may involve remapping up the seven characters that are @@ -536,7 +536,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, const struct nls_table * cp) { int i,j,len; - wchar_t src_char; + __u16 src_char; for(i = 0, j = 0; i < maxlen; i++) { src_char = le16_to_cpu(source[i]); -- cgit v1.2.3 From 848f3fce45d2ba93e10b5e9d65bcae0d9269ad0d Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: Do not interpret oplock break responses as responses to an unrelated command .. even if the multiplex ids match. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 2 ++ fs/cifs/cifs_debug.c | 7 ++++++- fs/cifs/cifsglob.h | 2 +- fs/cifs/connect.c | 10 +++++++--- fs/cifs/transport.c | 1 - 5 files changed, 16 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index de8858028d64..de63a0e3f4ce 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -10,6 +10,8 @@ different users from the same client to the same server. Fix oops in cifs_close. Add mount option for remapping reserved characters in filenames (also allow recognizing files with created by SFU which have any of these seven reserved characters, except backslash, to be recognized). +Fix invalid transact2 message (we were sometimes trying to interpret +oplock breaks as SMB responses). Version 1.31 ------------ diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index e7bd93e6226d..efa099165b22 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -111,7 +111,12 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, mid_q_entry, qhead); if(mid_entry) { - length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n",mid_entry->midState,mid_entry->command,mid_entry->pid,mid_entry->tsk,mid_entry->mid); + length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n", + mid_entry->midState, + (int)mid_entry->command, + mid_entry->pid, + mid_entry->tsk, + mid_entry->mid); buf += length; } } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 1b3082d79379..fe1409799513 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -313,12 +313,12 @@ struct mid_q_entry { __u16 mid; /* multiplex id */ __u16 pid; /* process id */ __u32 sequence_number; /* for CIFS signing */ - __u16 command; /* smb command code */ struct timeval when_sent; /* time when smb sent */ struct cifsSesInfo *ses; /* smb was sent to this server */ struct task_struct *tsk; /* task waiting for response */ struct smb_hdr *resp_buf; /* response buffer */ int midState; /* wish this were enum but can not pass to wait_event */ + __u8 command; /* smb command code */ }; struct oplock_q_entry { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 1f22b85324cf..383e55fa7d26 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -361,9 +361,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) mid_q_entry, qhead); - if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED)) { - cFYI(1, - (" Mid 0x%x matched - waking up ",mid_entry->mid)); + if ((mid_entry->mid == smb_buffer->Mid) + && (mid_entry->midState == + MID_REQUEST_SUBMITTED) + && (mid_entry->command == + smb_buffer->Command)) { + cFYI(1,("Found Mid 0x%x wake up" + ,mid_entry->mid)); task_to_wake = mid_entry->tsk; mid_entry->resp_buf = smb_buffer; diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index a9e4f989b7f7..aab62ed46982 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -189,7 +189,6 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, struct msghdr smb_msg; number_of_pages += 1; /* account for SMB header */ struct kvec * piov = kmalloc(number_of_pages * sizeof(struct kvec)); - if(i=0;i Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: CIFS ioctl needed by umount.cifs utility Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 4 ++++ fs/cifs/cifspdu.h | 2 +- fs/cifs/ioctl.c | 31 +++++++++++++++++++++++-------- 3 files changed, 28 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 3d5365b9f5ba..461a706b237b 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -190,6 +190,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) #ifdef CONFIG_CIFS_EXPERIMENTAL /* BB we could add a second check for a QFS Unix capability bit */ +/* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ if (pTcon->ses->capabilities & CAP_UNIX) rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); @@ -599,6 +600,9 @@ struct file_operations cifs_dir_ops = { #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ +#ifdef CONFIG_CIFS_POSIX + .ioctl = cifs_ioctl, +#endif /* CONFIG_CIFS_POSIX */ }; static void diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 5b352890f092..e3e92615705e 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1556,7 +1556,7 @@ typedef struct { #define CIFS_UNIX_POSIX_ACL_CAP 0x00000002 /* support getfacl/setfacl */ #define CIFS_UNIX_XATTR_CAP 0x00000004 /* support new namespace */ #define CIFS_UNIX_EXTATTR_CAP 0x00000008 /* support chattr/chflag */ - +#define CIFS_POSIX_EXTENSIONS 0x00000010 /* support for new QFSInfo */ typedef struct { /* For undefined recommended transfer size return -1 in that field */ __le32 OptimalTransferSize; /* bsize on some os, iosize on other os */ diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index a4f1c34a8dc7..711bb7a3a98e 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -29,6 +29,8 @@ #include "cifs_debug.h" #include "cifsfs.h" +#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) + int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) { @@ -36,8 +38,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep, #ifdef CONFIG_CIFS_POSIX __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; - __u64 caps; #endif /* CONFIG_CIFS_POSIX */ + __u64 caps; int xid; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; @@ -46,12 +48,11 @@ int cifs_ioctl (struct inode * inode, struct file * filep, xid = GetXid(); + cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); + cifs_sb = CIFS_SB(inode->i_sb); tcon = cifs_sb->tcon; - if (pSMBFile == NULL) - goto cifs_ioctl_out; -#ifdef CONFIG_CIFS_POSIX if(tcon) caps = le64_to_cpu(tcon->fsUnixInfo.Capability); else { @@ -59,10 +60,22 @@ int cifs_ioctl (struct inode * inode, struct file * filep, goto cifs_ioctl_out; } - cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); switch(command) { + case CIFS_IOC_CHECKUMOUNT: + cFYI(1,("User unmount attempted")); + /* BB FIXME - add missing code here FIXME */ + if(cifs_sb->mnt_uid == current->uid) + rc = 0; + else { + rc = -EACCES; + cFYI(1,("uids do not match")); + } + break; +#ifdef CONFIG_CIFS_POSIX case EXT2_IOC_GETFLAGS: if(CIFS_UNIX_EXTATTR_CAP & caps) { + if (pSMBFile == NULL) + goto cifs_ioctl_out; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); if(rc == 0) @@ -78,17 +91,19 @@ int cifs_ioctl (struct inode * inode, struct file * filep, rc = -EFAULT; goto cifs_ioctl_out; } - /* rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, + if (pSMBFile == NULL) + goto cifs_ioctl_out; + /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ } cFYI(1,("set flags not implemented yet")); break; +#endif /* CONFIG_CIFS_POSIX */ default: cFYI(1,("unsupported ioctl")); - return rc; + break; } -#endif /* CONFIG_CIFS_POSIX */ cifs_ioctl_out: FreeXid(xid); -- cgit v1.2.3 From c81156dd217818c143a09b6a744e797a04571e99 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: cleanup of ifdefs usage so it is more consistent And fix to not needlessly send new POSIX QFSInfo when server does not explicitly claim support for the new protocol extensions. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsfs.c | 21 +++++++++++---------- fs/cifs/cifsglob.h | 4 +++- fs/cifs/ioctl.c | 21 +++++++++++---------- 3 files changed, 25 insertions(+), 21 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 461a706b237b..6322aada491f 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -169,7 +169,8 @@ cifs_put_super(struct super_block *sb) static int cifs_statfs(struct super_block *sb, struct kstatfs *buf) { - int xid, rc = -EOPNOTSUPP; + int xid; + int rc = -EOPNOTSUPP; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; @@ -181,17 +182,18 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) buf->f_type = CIFS_MAGIC_NUMBER; /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ - buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would presumably - be length of total path, note that some servers may be - able to support more than this, but best to be safe - since Win2k and others can not handle very long filenames */ + buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would + presumably be total path, but note + that some servers (includinng Samba 3) + have a shorter maximum path */ buf->f_files = 0; /* undefined */ buf->f_ffree = 0; /* unlimited */ #ifdef CONFIG_CIFS_EXPERIMENTAL /* BB we could add a second check for a QFS Unix capability bit */ /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ - if (pTcon->ses->capabilities & CAP_UNIX) + if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & + le64_to_cpu(pTcon->fsUnixInfo.Capability))) rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); /* Only need to call the old QFSInfo if failed @@ -204,9 +206,10 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf) int f_type; __fsid_t f_fsid; int f_namelen; */ - /* BB get from info put in tcon struct at mount time with call to QFSAttrInfo */ + /* BB get from info in tcon struct at mount time call to QFSAttrInfo */ FreeXid(xid); - return 0; /* always return success? what if volume is no longer available? */ + return 0; /* always return success? what if volume is no + longer available? */ } static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) @@ -600,9 +603,7 @@ struct file_operations cifs_dir_ops = { #ifdef CONFIG_CIFS_EXPERIMENTAL .dir_notify = cifs_dir_notify, #endif /* CONFIG_CIFS_EXPERIMENTAL */ -#ifdef CONFIG_CIFS_POSIX .ioctl = cifs_ioctl, -#endif /* CONFIG_CIFS_POSIX */ }; static void diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index fe1409799513..322a12450ad3 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -318,7 +318,9 @@ struct mid_q_entry { struct task_struct *tsk; /* task waiting for response */ struct smb_hdr *resp_buf; /* response buffer */ int midState; /* wish this were enum but can not pass to wait_event */ - __u8 command; /* smb command code */ + __u8 command; /* smb command code */ + unsigned multiPart:1; /* multiple responses to one SMB request */ + unsigned largeBuf:1; /* if valid response, is pointer to large buf */ }; struct oplock_q_entry { diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c index 711bb7a3a98e..b0ea6687ab55 100644 --- a/fs/cifs/ioctl.c +++ b/fs/cifs/ioctl.c @@ -35,35 +35,37 @@ int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg) { int rc = -ENOTTY; /* strange error - but the precedent */ + int xid; + struct cifs_sb_info *cifs_sb; #ifdef CONFIG_CIFS_POSIX __u64 ExtAttrBits = 0; __u64 ExtAttrMask = 0; -#endif /* CONFIG_CIFS_POSIX */ __u64 caps; - int xid; - struct cifs_sb_info *cifs_sb; struct cifsTconInfo *tcon; struct cifsFileInfo *pSMBFile = (struct cifsFileInfo *)filep->private_data; +#endif /* CONFIG_CIFS_POSIX */ xid = GetXid(); cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); cifs_sb = CIFS_SB(inode->i_sb); - tcon = cifs_sb->tcon; +#ifdef CONFIG_CIFS_POSIX + tcon = cifs_sb->tcon; if(tcon) caps = le64_to_cpu(tcon->fsUnixInfo.Capability); else { rc = -EIO; - goto cifs_ioctl_out; + FreeXid(xid); + return -EIO; } +#endif /* CONFIG_CIFS_POSIX */ switch(command) { case CIFS_IOC_CHECKUMOUNT: cFYI(1,("User unmount attempted")); - /* BB FIXME - add missing code here FIXME */ if(cifs_sb->mnt_uid == current->uid) rc = 0; else { @@ -75,7 +77,7 @@ int cifs_ioctl (struct inode * inode, struct file * filep, case EXT2_IOC_GETFLAGS: if(CIFS_UNIX_EXTATTR_CAP & caps) { if (pSMBFile == NULL) - goto cifs_ioctl_out; + break; rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, &ExtAttrBits, &ExtAttrMask); if(rc == 0) @@ -89,10 +91,10 @@ int cifs_ioctl (struct inode * inode, struct file * filep, if(CIFS_UNIX_EXTATTR_CAP & caps) { if(get_user(ExtAttrBits,(int __user *)arg)) { rc = -EFAULT; - goto cifs_ioctl_out; + break; } if (pSMBFile == NULL) - goto cifs_ioctl_out; + break; /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, extAttrBits, &ExtAttrMask);*/ @@ -105,7 +107,6 @@ int cifs_ioctl (struct inode * inode, struct file * filep, break; } -cifs_ioctl_out: FreeXid(xid); return rc; } -- cgit v1.2.3 From b8643e1b5253a6a51da5574a55a2f9148e255cfd Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: Do not use large smb buffers in response path unless response is larger than 256 bytes. This cuts more than 1/3 of the large memory allocations that cifs does and should be a huge help to memory pressure under stress. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifs_debug.c | 11 +++++--- fs/cifs/connect.c | 80 ++++++++++++++++++++++++++++++++++------------------ fs/cifs/transport.c | 7 +++-- 3 files changed, 65 insertions(+), 33 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index efa099165b22..bff2ec6e054a 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -1,7 +1,7 @@ /* * fs/cifs_debug.c * - * Copyright (C) International Business Machines Corp., 2000,2003 + * Copyright (C) International Business Machines Corp., 2000,2005 * * Modified by Steve French (sfrench@us.ibm.com) * @@ -92,8 +92,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, length = sprintf(buf, "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", - i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), - ses->serverOS, ses->serverNOS, ses->capabilities,ses->status); + i, ses->serverName, ses->serverDomain, + atomic_read(&ses->inUse), + ses->serverOS, ses->serverNOS, + ses->capabilities,ses->status); buf += length; if(ses->server) { buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", @@ -207,7 +209,8 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, buf += item_length; item_length = sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n", - bufAllocCount.counter,cifs_min_rcv + tcpSesAllocCount.counter); + bufAllocCount.counter, + cifs_min_rcv + tcpSesAllocCount.counter); length += item_length; buf += item_length; item_length = diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 383e55fa7d26..390f22fa3439 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1,7 +1,7 @@ /* * fs/cifs/connect.c * - * Copyright (C) International Business Machines Corp., 2002,2004 + * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include "cifspdu.h" @@ -198,6 +199,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) int length; unsigned int pdu_length, total_read; struct smb_hdr *smb_buffer = NULL; + struct smb_hdr *bigbuf = NULL; + struct smb_hdr *smallbuf = NULL; struct msghdr smb_msg; struct kvec iov; struct socket *csocket = server->ssocket; @@ -206,6 +209,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct task_struct *task_to_wake = NULL; struct mid_q_entry *mid_entry; char *temp; + int isLargeBuf = FALSE; daemonize("cifsd"); allow_signal(SIGKILL); @@ -223,17 +227,33 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } while (server->tcpStatus != CifsExiting) { - if (smb_buffer == NULL) - smb_buffer = cifs_buf_get(); - else - memset(smb_buffer, 0, sizeof (struct smb_hdr)); - - if (smb_buffer == NULL) { - cERROR(1,("Can not get memory for SMB response")); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ * 3); /* give system time to free memory */ - continue; + if (bigbuf == NULL) { + bigbuf = cifs_buf_get(); + if(bigbuf == NULL) { + cERROR(1,("No memory for large SMB response")); + msleep(3000); + /* retry will check if exiting */ + continue; + } + } else if(isLargeBuf) { + /* we are reusing a dirtry large buf, clear its start */ + memset(bigbuf, 0, sizeof (struct smb_hdr)); } + + if (smallbuf == NULL) { + smallbuf = cifs_small_buf_get(); + if(smallbuf == NULL) { + cERROR(1,("No memory for SMB response")); + msleep(1000); + /* retry will check if exiting */ + continue; + } + /* beginning of smb buffer is cleared in our buf_get */ + } else /* if existing small buf clear beginning */ + memset(smallbuf, 0, sizeof (struct smb_hdr)); + + isLargeBuf = FALSE; + smb_buffer = smallbuf; iov.iov_base = smb_buffer; iov.iov_len = 4; smb_msg.msg_control = NULL; @@ -251,8 +271,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) csocket = server->ssocket; continue; } else if ((length == -ERESTARTSYS) || (length == -EAGAIN)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); /* minimum sleep to prevent looping + msleep(1); /* minimum sleep to prevent looping allowing socket to clear and app threads to set tcpStatus CifsNeedReconnect if server hung */ continue; @@ -295,8 +314,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } else { /* give server a second to clean up before reconnect attempt */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); + msleep(1000); /* always try 445 first on reconnect since we get NACK on some if we ever connected to port 139 (the NACK is @@ -325,6 +343,11 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) wake_up(&server->response_q); continue; } else { /* length ok */ + if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { + isLargeBuf = TRUE; + memcpy(bigbuf, smallbuf, 4); + smb_buffer = bigbuf; + } length = 0; iov.iov_base = 4 + (char *)smb_buffer; iov.iov_len = pdu_length; @@ -377,6 +400,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } spin_unlock(&GlobalMid_Lock); if (task_to_wake) { + if(isLargeBuf) + bigbuf = NULL; + else + smallbuf = NULL; smb_buffer = NULL; /* will be freed by users thread after he is done */ wake_up_process(task_to_wake); } else if (is_valid_oplock_break(smb_buffer) == FALSE) { @@ -406,15 +433,17 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) and get out of SendReceive. */ wake_up_all(&server->request_q); /* give those requests time to exit */ - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/8); - + msleep(125); + if(server->ssocket) { sock_release(csocket); server->ssocket = NULL; } - if (smb_buffer) /* buffer usually freed in free_mid - need to free it on error or exit */ - cifs_buf_release(smb_buffer); + /* buffer usuallly freed in free_mid - need to free it here on exit */ + if (bigbuf != NULL) + cifs_buf_release(bigbuf); + if (smallbuf != NULL) + cifs_small_buf_release(smallbuf); read_lock(&GlobalSMBSeslock); if (list_empty(&server->pending_mid_q)) { @@ -444,17 +473,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } spin_unlock(&GlobalMid_Lock); read_unlock(&GlobalSMBSeslock); - set_current_state(TASK_INTERRUPTIBLE); /* 1/8th of sec is more than enough time for them to exit */ - schedule_timeout(HZ/8); + msleep(125); } if (list_empty(&server->pending_mid_q)) { /* mpx threads have not exited yet give them at least the smb send timeout time for long ops */ cFYI(1, ("Wait for exit from demultiplex thread")); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(46 * HZ); + msleep(46); /* if threads still have not exited they are probably never coming home not much else we can do but free the memory */ } @@ -469,9 +496,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) length + cifs_min_rcv, GFP_KERNEL); } - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/4); + + msleep(250); return 0; } diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index aab62ed46982..f9e16b39898c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -1,7 +1,7 @@ /* * fs/cifs/transport.c * - * Copyright (C) International Business Machines Corp., 2002,2004 + * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -79,7 +79,10 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) list_del(&midEntry->qhead); atomic_dec(&midCount); spin_unlock(&GlobalMid_Lock); - cifs_buf_release(midEntry->resp_buf); + if(midEntry->largeBuf) + cifs_buf_release(midEntry->resp_buf); + else + cifs_small_buf_release(midEntry->resp_buf); mempool_free(midEntry, cifs_mid_poolp); } -- cgit v1.2.3 From 099a58f681ed951434574ec39bdfe87055bafe73 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:07 -0700 Subject: [PATCH] cifs: Missing initialization for largeBuf flag left out of previous changeset Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 6 +++++- fs/cifs/README | 19 ++++++++++++++++++- fs/cifs/connect.c | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index de63a0e3f4ce..be3a57509e60 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -11,7 +11,11 @@ cifs_close. Add mount option for remapping reserved characters in filenames (also allow recognizing files with created by SFU which have any of these seven reserved characters, except backslash, to be recognized). Fix invalid transact2 message (we were sometimes trying to interpret -oplock breaks as SMB responses). +oplock breaks as SMB responses). Add ioctl for checking that the +current uid matches the uid of the mounter (needed by umount.cifs). +Reduce the number of large buffer allocations in cifs response processing +(significantly reduces memory pressure under heavy stress with multiple +processes accessing the same server at the same time). Version 1.31 ------------ diff --git a/fs/cifs/README b/fs/cifs/README index 93900fc4adaa..48c37a6e9c3f 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -75,7 +75,7 @@ Allowing User Mounts ==================== To permit users to mount and unmount over directories they own is possible with the cifs vfs. A way to enable such mounting is to mark the mount.cifs -utility as suid (e.g. "chmod +s /sbin/mount/cifs). To enable users to +utility as suid (e.g. "chmod +s /sbin/mount.cifs). To enable users to umount shares they mount requires 1) mount.cifs version 1.4 or later 2) an entry for the share in /etc/fstab indicating that a user may @@ -97,6 +97,23 @@ mount.cifs with the following flag: There is a corresponding manual page for cifs mounting in the Samba 3.0 and later source tree in docs/manpages/mount.cifs.8 +Allowing User Unmounts +====================== +To permit users to ummount directories that they have user mounted (see above), +the utility umount.cifs may be used. It may be invoked directly, or if +umount.cifs is placed in /sbin, umount -i can invoke the cifs umount helper +(at least for most versions of the umount utility) for umount of cifs +mounts. As with mount.cifs, to enable user unmounts umount.cifs must be marked +as suid (e.g. "chmod +s /sbin/umount.cifs"). For this utility to succeed +the target path must be a cifs mount, and the uid of the current user must +match the uid of the user who mounted the resource. + +Also note that the customary way of allowing user mounts and unmounts is +(instead of using mount.cifs and unmount.cifs as suid) to add a line +to the file /etc/fstab for each //server/share you wish to mount, but +this can become unwieldy when potential mount targets include many +or unpredictable UNC names. + Samba Considerations ==================== To get the maximum benefit from the CIFS VFS, we recommend using a server that diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 390f22fa3439..c999583d11b0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -396,6 +396,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) smb_buffer; mid_entry->midState = MID_RESPONSE_RECEIVED; + if(isLargeBuf) + mid_entry->largeBuf = 1; + else + mid_entry->largeBuf = 0; } } spin_unlock(&GlobalMid_Lock); -- cgit v1.2.3 From 433dc24f24b409fb130f638aa85470a0eb666206 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:08 -0700 Subject: [PATCH] cifs: remove cifs_kcalloc and check for NULL return on kcalloc in session initialization Suggested by: Adrian Bunk and Dave Miller Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifs_debug.c | 15 +++++-- fs/cifs/connect.c | 124 ++++++++++++++++++++++++++++----------------------- 2 files changed, 80 insertions(+), 59 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index bff2ec6e054a..4061e43471c1 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -89,14 +89,21 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, list_for_each(tmp, &GlobalSMBSessionList) { i++; ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); - length = - sprintf(buf, - "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", + if((ses->serverDomain == NULL) || (ses->serverOS == NULL) || + (ses->serverNOS == NULL)) { + buf += sprintf("\nentry for %s not fully displayed\n\t", + ses->serverName); + + } else { + length = + sprintf(buf, + "\n%d) Name: %s Domain: %s Mounts: %d ServerOS: %s \n\tServerNOS: %s\tCapabilities: 0x%x\n\tSMB session status: %d\t", i, ses->serverName, ses->serverDomain, atomic_read(&ses->inUse), ses->serverOS, ses->serverNOS, ses->capabilities,ses->status); - buf += length; + buf += length; + } if(ses->server) { buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req Active: %d", ses->server->tcpStatus, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index c999583d11b0..8a8aa785e7b7 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -505,16 +505,6 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) return 0; } -static void * -cifs_kcalloc(size_t size, unsigned int __nocast type) -{ - void *addr; - addr = kmalloc(size, type); - if (addr) - memset(addr, 0, size); - return addr; -} - static int cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) { @@ -632,7 +622,11 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* go from value to value + temp_len condensing double commas to singles. Note that this ends up allocating a few bytes too many, which is ok */ - vol->password = cifs_kcalloc(temp_len, GFP_KERNEL); + vol->password = kcalloc(1, temp_len, GFP_KERNEL); + if(vol->password == NULL) { + printk("CIFS: no memory for pass\n"); + return 1; + } for(i=0,j=0;ipassword[j] = value[i]; if(value[i] == separator[0] && value[i+1] == separator[0]) { @@ -642,7 +636,11 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) } vol->password[j] = 0; } else { - vol->password = cifs_kcalloc(temp_len + 1, GFP_KERNEL); + vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL); + if(vol->password == NULL) { + printk("CIFS: no memory for pass\n"); + return 1; + } strcpy(vol->password, value); } } else if (strnicmp(data, "ip", 2) == 0) { @@ -1104,7 +1102,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, sessinit is sent but no second negprot */ struct rfc1002_session_packet * ses_init_buf; struct smb_hdr * smb_buf; - ses_init_buf = cifs_kcalloc(sizeof(struct rfc1002_session_packet), GFP_KERNEL); + ses_init_buf = kcalloc(1, sizeof(struct rfc1002_session_packet), GFP_KERNEL); if(ses_init_buf) { ses_init_buf->trailer.session_req.called_len = 32; rfc1002mangle(ses_init_buf->trailer.session_req.called_name, @@ -1751,7 +1749,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, /* We look for obvious messed up bcc or strings in response so we do not go off the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ - ses->serverOS = cifs_kcalloc(2 * (len + 1), GFP_KERNEL); + ses->serverOS = kcalloc(1, 2 * (len + 1), GFP_KERNEL); + if(ses->serverOS == NULL) + goto sesssetup_nomem; cifs_strfromUCS_le(ses->serverOS, (wchar_t *)bcc_ptr, len,nls_codepage); bcc_ptr += 2 * (len + 1); @@ -1761,7 +1761,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, if (remaining_words > 0) { len = UniStrnlen((wchar_t *)bcc_ptr, remaining_words-1); - ses->serverNOS =cifs_kcalloc(2 * (len + 1),GFP_KERNEL); + ses->serverNOS = kcalloc(1, 2 * (len + 1),GFP_KERNEL); + if(ses->serverNOS == NULL) + goto sesssetup_nomem; cifs_strfromUCS_le(ses->serverNOS, (wchar_t *)bcc_ptr,len,nls_codepage); bcc_ptr += 2 * (len + 1); @@ -1774,10 +1776,12 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, } remaining_words -= len + 1; if (remaining_words > 0) { - len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); + len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ ses->serverDomain = - cifs_kcalloc(2*(len+1),GFP_KERNEL); + kcalloc(1, 2*(len+1),GFP_KERNEL); + if(ses->serverDomain == NULL) + goto sesssetup_nomem; cifs_strfromUCS_le(ses->serverDomain, (wchar_t *)bcc_ptr,len,nls_codepage); bcc_ptr += 2 * (len + 1); @@ -1785,21 +1789,25 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, ses->serverDomain[1+(2*len)] = 0; } /* else no more room so create dummy domain string */ else - ses->serverDomain = - cifs_kcalloc(2, - GFP_KERNEL); + ses->serverDomain = + kcalloc(1, 2, GFP_KERNEL); } else { /* no room so create dummy domain and NOS string */ + /* if these kcallocs fail not much we + can do, but better to not fail the + sesssetup itself */ ses->serverDomain = - cifs_kcalloc(2, GFP_KERNEL); + kcalloc(1, 2, GFP_KERNEL); ses->serverNOS = - cifs_kcalloc(2, GFP_KERNEL); + kcalloc(1, 2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); + ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL); + if(ses->serverOS == NULL) + goto sesssetup_nomem; strncpy(ses->serverOS,bcc_ptr, len); bcc_ptr += len; @@ -1807,14 +1815,18 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); + ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL); + if(ses->serverNOS == NULL) + goto sesssetup_nomem; strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverDomain = cifs_kcalloc(len + 1,GFP_KERNEL); + ses->serverDomain = kcalloc(1, len + 1,GFP_KERNEL); + if(ses->serverDomain == NULL) + goto sesssetup_nomem; strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; @@ -1834,7 +1846,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses, smb_buffer_response->WordCount)); rc = -EIO; } - +sesssetup_nomem: /* do not return an error on nomem for the info strings, + since that could make reconnection harder, and + reconnection might be needed to free memory */ if (smb_buffer) cifs_buf_release(smb_buffer); @@ -2011,7 +2025,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ ses->serverOS = - cifs_kcalloc(2 * (len + 1), GFP_KERNEL); + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (wchar_t *) bcc_ptr, len, @@ -2025,7 +2039,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, remaining_words - 1); ses->serverNOS = - cifs_kcalloc(2 * (len + 1), + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverNOS, (wchar_t *)bcc_ptr, @@ -2038,7 +2052,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, if (remaining_words > 0) { len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ - ses->serverDomain = cifs_kcalloc(2*(len+1),GFP_KERNEL); + ses->serverDomain = kcalloc(1, 2*(len+1),GFP_KERNEL); cifs_strfromUCS_le(ses->serverDomain, (wchar_t *)bcc_ptr, len, @@ -2049,10 +2063,10 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, } /* else no more room so create dummy domain string */ else ses->serverDomain = - cifs_kcalloc(2,GFP_KERNEL); + kcalloc(1, 2,GFP_KERNEL); } else { /* no room so create dummy domain and NOS string */ - ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); - ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); + ses->serverDomain = kcalloc(1, 2, GFP_KERNEL); + ses->serverNOS = kcalloc(1, 2, GFP_KERNEL); } } else { /* ASCII */ @@ -2060,7 +2074,7 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - ses->serverOS = cifs_kcalloc(len + 1, GFP_KERNEL); + ses->serverOS = kcalloc(1, len + 1, GFP_KERNEL); strncpy(ses->serverOS, bcc_ptr, len); bcc_ptr += len; @@ -2068,14 +2082,14 @@ CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverNOS = cifs_kcalloc(len + 1,GFP_KERNEL); + ses->serverNOS = kcalloc(1, len + 1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverDomain = cifs_kcalloc(len + 1, GFP_KERNEL); + ses->serverDomain = kcalloc(1, len + 1, GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; @@ -2325,7 +2339,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ ses->serverOS = - cifs_kcalloc(2 * (len + 1), GFP_KERNEL); + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (wchar_t *) bcc_ptr, len, @@ -2340,7 +2354,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, remaining_words - 1); ses->serverNOS = - cifs_kcalloc(2 * (len + 1), + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses-> serverNOS, @@ -2357,7 +2371,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string is not always null terminated (for e.g. for Windows XP & 2000) */ ses->serverDomain = - cifs_kcalloc(2 * + kcalloc(1, 2 * (len + 1), GFP_KERNEL); @@ -2383,13 +2397,13 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, } /* else no more room so create dummy domain string */ else ses->serverDomain = - cifs_kcalloc(2, + kcalloc(1, 2, GFP_KERNEL); } else { /* no room so create dummy domain and NOS string */ ses->serverDomain = - cifs_kcalloc(2, GFP_KERNEL); + kcalloc(1, 2, GFP_KERNEL); ses->serverNOS = - cifs_kcalloc(2, GFP_KERNEL); + kcalloc(1, 2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); @@ -2397,7 +2411,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { ses->serverOS = - cifs_kcalloc(len + 1, + kcalloc(1, len + 1, GFP_KERNEL); strncpy(ses->serverOS, bcc_ptr, len); @@ -2408,7 +2422,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, len = strnlen(bcc_ptr, 1024); ses->serverNOS = - cifs_kcalloc(len + 1, + kcalloc(1, len + 1, GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; @@ -2417,7 +2431,7 @@ CIFSNTLMSSPNegotiateSessSetup(unsigned int xid, len = strnlen(bcc_ptr, 1024); ses->serverDomain = - cifs_kcalloc(len + 1, + kcalloc(1, len + 1, GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; @@ -2719,7 +2733,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, the end since (at least) WIN2K and Windows XP have a major bug in not null terminating last Unicode string in response */ ses->serverOS = - cifs_kcalloc(2 * (len + 1), GFP_KERNEL); + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses->serverOS, (wchar_t *) bcc_ptr, len, @@ -2734,7 +2748,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, remaining_words - 1); ses->serverNOS = - cifs_kcalloc(2 * (len + 1), + kcalloc(1, 2 * (len + 1), GFP_KERNEL); cifs_strfromUCS_le(ses-> serverNOS, @@ -2750,7 +2764,7 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words); /* last string not always null terminated (e.g. for Windows XP & 2000) */ ses->serverDomain = - cifs_kcalloc(2 * + kcalloc(1, 2 * (len + 1), GFP_KERNEL); @@ -2775,17 +2789,17 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, = 0; } /* else no more room so create dummy domain string */ else - ses->serverDomain = cifs_kcalloc(2,GFP_KERNEL); + ses->serverDomain = kcalloc(1, 2,GFP_KERNEL); } else { /* no room so create dummy domain and NOS string */ - ses->serverDomain = cifs_kcalloc(2, GFP_KERNEL); - ses->serverNOS = cifs_kcalloc(2, GFP_KERNEL); + ses->serverDomain = kcalloc(1, 2, GFP_KERNEL); + ses->serverNOS = kcalloc(1, 2, GFP_KERNEL); } } else { /* ASCII */ len = strnlen(bcc_ptr, 1024); if (((long) bcc_ptr + len) - (long) pByteArea(smb_buffer_response) <= BCC(smb_buffer_response)) { - ses->serverOS = cifs_kcalloc(len + 1,GFP_KERNEL); + ses->serverOS = kcalloc(1, len + 1,GFP_KERNEL); strncpy(ses->serverOS,bcc_ptr, len); bcc_ptr += len; @@ -2793,14 +2807,14 @@ CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverNOS = cifs_kcalloc(len+1,GFP_KERNEL); + ses->serverNOS = kcalloc(1, len+1,GFP_KERNEL); strncpy(ses->serverNOS, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; bcc_ptr++; len = strnlen(bcc_ptr, 1024); - ses->serverDomain = cifs_kcalloc(len+1,GFP_KERNEL); + ses->serverDomain = kcalloc(1, len+1,GFP_KERNEL); strncpy(ses->serverDomain, bcc_ptr, len); bcc_ptr += len; bcc_ptr[0] = 0; @@ -2912,7 +2926,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if(tcon->nativeFileSystem) kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = - cifs_kcalloc(length + 2, GFP_KERNEL); + kcalloc(1, length + 2, GFP_KERNEL); cifs_strfromUCS_le(tcon->nativeFileSystem, (wchar_t *) bcc_ptr, length, nls_codepage); @@ -2930,7 +2944,7 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, if(tcon->nativeFileSystem) kfree(tcon->nativeFileSystem); tcon->nativeFileSystem = - cifs_kcalloc(length + 1, GFP_KERNEL); + kcalloc(1, length + 1, GFP_KERNEL); strncpy(tcon->nativeFileSystem, bcc_ptr, length); } -- cgit v1.2.3 From 966ca9234754ece58870075972ef103e354de075 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:08 -0700 Subject: [PATCH] cifs: Fix caching problem pointed out by Dave Stahl and Vince Negri in which cifs can update the last modify time on a server modified file without invalidating the local cached data due to an intervening readdir. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/AUTHORS | 24 ++++++++++++------- fs/cifs/CHANGES | 8 +++++++ fs/cifs/cifsfs.h | 4 ++-- fs/cifs/cifssmb.c | 2 +- fs/cifs/readdir.c | 70 ++++++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 83 insertions(+), 25 deletions(-) (limited to 'fs') diff --git a/fs/cifs/AUTHORS b/fs/cifs/AUTHORS index acce36e25d2e..72fdc10dfdd7 100644 --- a/fs/cifs/AUTHORS +++ b/fs/cifs/AUTHORS @@ -4,13 +4,16 @@ Steve French (sfrench@samba.org) The author wishes to express his appreciation and thanks to: Andrew Tridgell (Samba team) for his early suggestions about smb/cifs VFS -improvements. Thanks to IBM for allowing me the time and test resources to pursue -this project. Jim McDonough from IBM (and the Samba Team) for his help. -The IBM Linux JFS team for explaining many esoteric Linux filesystem features. +improvements. Thanks to IBM for allowing me time and test resources to pursue +this project, to Jim McDonough from IBM (and the Samba Team) for his help, to +the IBM Linux JFS team for explaining many esoteric Linux filesystem features. +Jeremy Allison of the Samba team has done invaluable work in adding the server +side of the original CIFS Unix extensions and reviewing and implementing +portions of the newer CIFS POSIX extensions into the Samba 3 file server. Thank Dave Boutcher of IBM Rochester (author of the OS/400 smb/cifs filesystem client) -for proving years ago that a very good smb/cifs client could be done on a Unix like -operating system. Volker Lendecke, Andrew Tridgell, Urban Widmark, John Newbigin -and others for their work on the Linux smbfs module over the years. Thanks to +for proving years ago that very good smb/cifs clients could be done on Unix-like +operating systems. Volker Lendecke, Andrew Tridgell, Urban Widmark, John +Newbigin and others for their work on the Linux smbfs module. Thanks to the other members of the Storage Network Industry Association CIFS Technical Workgroup for their work specifying this highly complex protocol and finally thanks to the Samba team for their technical advice and encouragement. @@ -24,9 +27,11 @@ Shobhit Dayal Sergey Vlasov Richard Hughes Yury Umanets -Mark Hamzy +Mark Hamzy (for some of the early cifs IPv6 work) Domen Puncer -Jesper Juhl +Jesper Juhl (in particular for lots of whitespace/formatting cleanup) +Vince Negri and Dave Stahl (for finding an important caching bug) +Adrian Bunk (kcalloc cleanups) Test case and Bug Report contributors ------------------------------------- @@ -36,7 +41,8 @@ Rene Scharfe, Martin Josefsson, Alexander Wild, Anthony Liguori, Lars Muller, Urban Widmark, Massimiliano Ferrero, Howard Owen, Olaf Kirch, Kieron Briggs, Nick Millington and others. Also special mention to the Stanford Checker (SWAT) which pointed out many minor -bugs in error paths. +bugs in error paths. Valuable suggestions also have come from Al Viro +and Dave Miller. And thanks to the IBM LTC and Power test teams and SuSE testers for finding multiple bugs during excellent stress test runs. diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index be3a57509e60..0414eb325468 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,11 @@ +Version 1.33 +------------ +Fix caching problem, in which readdir of directory containing a file +which was cached could cause the file's time stamp to be updated +without invalidating the readahead data (so we could get stale +file data on the client for that file even as the server copy changed). + + Version 1.32 ------------ Fix oops in ls when Transact2 FindFirst (or FindNext) returns more than one diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index e0e46f4bff97..8f742796a627 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsfs.h * - * Copyright (c) International Business Machines Corp., 2002 + * Copyright (c) International Business Machines Corp., 2002, 2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.32" +#define CIFS_VERSION "1.33" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f7c4914c3dd9..b102ddb977ca 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -464,7 +464,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, &length, 0); if (rc) - cFYI(1, (" Tree disconnect failed %d", rc)); + cFYI(1, ("Tree disconnect failed %d", rc)); if (smb_buffer) cifs_small_buf_release(smb_buffer); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 7ca876b6f2ab..39170cffcad8 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -3,7 +3,7 @@ * * Directory search handling * - * Copyright (C) International Business Machines Corp., 2004 + * Copyright (C) International Business Machines Corp., 2004, 2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -65,14 +65,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file, struct cifsTconInfo *pTcon; int rc = 0; - cFYI(1, ("For %s ", qstring->name)); + cFYI(1, ("For %s", qstring->name)); cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; qstring->hash = full_name_hash(qstring->name, qstring->len); tmp_dentry = d_lookup(file->f_dentry, qstring); if (tmp_dentry) { - cFYI(0, (" existing dentry with inode 0x%p", tmp_dentry->d_inode)); + cFYI(0, ("existing dentry with inode 0x%p", tmp_dentry->d_inode)); *ptmp_inode = tmp_dentry->d_inode; /* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/ if(*ptmp_inode == NULL) { @@ -105,8 +105,11 @@ static int construct_dentry(struct qstr *qstring, struct file *file, } static void fill_in_inode(struct inode *tmp_inode, - FILE_DIRECTORY_INFO *pfindData, int *pobject_type) + FILE_DIRECTORY_INFO *pfindData, int *pobject_type, int isNewInode) { + loff_t local_size; + struct timespec local_mtime; + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); __u32 attr = le32_to_cpu(pfindData->ExtFileAttributes); @@ -116,6 +119,10 @@ static void fill_in_inode(struct inode *tmp_inode, cifsInfo->cifsAttrs = attr; cifsInfo->time = jiffies; + /* save mtime and size */ + local_mtime = tmp_inode->i_mtime; + local_size = tmp_inode->i_size; + /* Linux can not store file creation time unfortunately so ignore it */ tmp_inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); @@ -134,7 +141,6 @@ static void fill_in_inode(struct inode *tmp_inode, tmp_inode->i_mode = cifs_sb->mnt_file_mode; } - cFYI(0,("CIFS FFIRST: Attributes came in as 0x%x",attr)); if (attr & ATTR_DIRECTORY) { *pobject_type = DT_DIR; /* override default perms since we do not lock dirs */ @@ -175,30 +181,46 @@ static void fill_in_inode(struct inode *tmp_inode, (unsigned long)tmp_inode->i_size, tmp_inode->i_blocks, tmp_inode->i_blksize)); if (S_ISREG(tmp_inode->i_mode)) { - cFYI(1, (" File inode ")); + cFYI(1, ("File inode")); tmp_inode->i_op = &cifs_file_inode_ops; if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) tmp_inode->i_fop = &cifs_file_direct_ops; else tmp_inode->i_fop = &cifs_file_ops; tmp_inode->i_data.a_ops = &cifs_addr_ops; + + if(isNewInode) + return; /* No sense invalidating pages for new inode since we + have not started caching readahead file data yet */ + + if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && + (local_size == tmp_inode->i_size)) { + cFYI(1, ("inode exists but unchanged")); + } else { + /* file may have changed on server */ + cFYI(1, ("invalidate inode, readdir detected change")); + invalidate_remote_inode(tmp_inode); + } } else if (S_ISDIR(tmp_inode->i_mode)) { - cFYI(1, (" Directory inode")); + cFYI(1, ("Directory inode")); tmp_inode->i_op = &cifs_dir_inode_ops; tmp_inode->i_fop = &cifs_dir_ops; } else if (S_ISLNK(tmp_inode->i_mode)) { - cFYI(1, (" Symbolic Link inode ")); + cFYI(1, ("Symbolic Link inode")); tmp_inode->i_op = &cifs_symlink_inode_ops; } else { - cFYI(1, (" Init special inode ")); + cFYI(1, ("Init special inode")); init_special_inode(tmp_inode, tmp_inode->i_mode, tmp_inode->i_rdev); } } static void unix_fill_in_inode(struct inode *tmp_inode, - FILE_UNIX_INFO *pfindData, int *pobject_type) + FILE_UNIX_INFO *pfindData, int *pobject_type, int isNewInode) { + loff_t local_size; + struct timespec local_mtime; + struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode); struct cifs_sb_info *cifs_sb = CIFS_SB(tmp_inode->i_sb); @@ -208,6 +230,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode, cifsInfo->time = jiffies; atomic_inc(&cifsInfo->inUse); + /* save mtime and size */ + local_mtime = tmp_inode->i_mtime; + local_size = tmp_inode->i_size; + tmp_inode->i_atime = cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastAccessTime)); tmp_inode->i_mtime = @@ -265,6 +291,19 @@ static void unix_fill_in_inode(struct inode *tmp_inode, else tmp_inode->i_fop = &cifs_file_ops; tmp_inode->i_data.a_ops = &cifs_addr_ops; + + if(isNewInode) + return; /* No sense invalidating pages for new inode since we + have not started caching readahead file data yet */ + + if (timespec_equal(&tmp_inode->i_mtime, &local_mtime) && + (local_size == tmp_inode->i_size)) { + cFYI(1, ("inode exists but unchanged")); + } else { + /* file may have changed on server */ + cFYI(1, ("invalidate inode, readdir detected change")); + invalidate_remote_inode(tmp_inode); + } } else if (S_ISDIR(tmp_inode->i_mode)) { cFYI(1, ("Directory inode")); tmp_inode->i_op = &cifs_dir_inode_ops; @@ -321,7 +360,7 @@ static int initiate_cifs_search(const int xid, struct file *file) return -ENOMEM; } - cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); + cFYI(1, ("Full path: %s start at: %lld", full_path, file->f_pos)); ffirst_retry: /* test for Unix extensions */ @@ -666,10 +705,15 @@ static int cifs_filldir(char *pfindEntry, struct file *file, insert_inode_hash(tmp_inode); } + /* we pass in rc below, indicating whether it is a new inode, + so we can figure out whether to invalidate the inode cached + data if the file has changed */ if(pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) { - unix_fill_in_inode(tmp_inode,(FILE_UNIX_INFO *)pfindEntry,&obj_type); + unix_fill_in_inode(tmp_inode, + (FILE_UNIX_INFO *)pfindEntry,&obj_type, rc); } else { - fill_in_inode(tmp_inode,(FILE_DIRECTORY_INFO *)pfindEntry,&obj_type); + fill_in_inode(tmp_inode, + (FILE_DIRECTORY_INFO *)pfindEntry,&obj_type, rc); } rc = filldir(direntry,qstring.name,qstring.len,file->f_pos,tmp_inode->i_ino,obj_type); -- cgit v1.2.3 From 09d1db5c6131232f764046160c29118cd4e5e646 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:08 -0700 Subject: [PATCH] cifs: improve check for search entry going beyond end of SMB transact Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/README | 8 ++--- fs/cifs/cifssmb.c | 89 +++++++++++++++++++++++++++++++------------------------ fs/cifs/connect.c | 62 ++++++++++++++++++++++++-------------- fs/cifs/readdir.c | 11 +++++-- 4 files changed, 102 insertions(+), 68 deletions(-) (limited to 'fs') diff --git a/fs/cifs/README b/fs/cifs/README index 48c37a6e9c3f..bec7b3fc8a72 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -420,7 +420,7 @@ Misc /proc/fs/cifs Flags and Debug Info ======================================= Informational pseudo-files: DebugData Displays information about active CIFS sessions - and shares. + and shares, as well as the cifs.ko version. Stats Lists summary resource usage information as well as per share statistics, if CONFIG_CIFS_STATS in enabled in the kernel configuration. @@ -477,7 +477,7 @@ and for more extensive tracing including the start of smb requests and responses Two other experimental features are under development and to test require enabling CONFIG_CIFS_EXPERIMENTAL - More efficient write operations and SMB buffer handling + More efficient write operations DNOTIFY fcntl: needed for support of directory change notification and perhaps later for file leases) @@ -495,8 +495,8 @@ returned success. Also note that "cat /proc/fs/cifs/DebugData" will display information about the active sessions and the shares that are mounted. Note: NTLMv2 enablement -will not work since they its implementation is not quite complete yet. -Do not alter these configuration values unless you are doing specific testing. +will not work since its implementation is not quite complete yet. Do not alter +the ExtendedSecurity configuration value unless you are doing specific testing. Enabling extended security works to Windows 2000 Workstations and XP but not to Windows 2000 server or Samba since it does not usually send "raw NTLMSSP" (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which support is not diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b102ddb977ca..834297f7b5e1 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -75,7 +75,8 @@ static void mark_open_files_invalid(struct cifsTconInfo * pTcon) } } write_unlock(&GlobalSMBSeslock); - /* BB Add call to invalidate_inodes(sb) for all superblocks mounted to this tcon */ + /* BB Add call to invalidate_inodes(sb) for all superblocks mounted + to this tcon */ } /* If the return code is zero, this function must fill in request_buf pointer */ @@ -92,8 +93,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if((tcon->ses) && (tcon->ses->server)){ struct nls_table *nls_codepage; /* Give Demultiplex thread up to 10 seconds to - reconnect, should be greater than cifs socket - timeout which is 7 seconds */ + reconnect, should be greater than cifs socket + timeout which is 7 seconds */ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { wait_event_interruptible_timeout(tcon->ses->server->response_q, (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); @@ -103,8 +104,9 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, (tcon->ses->status == CifsExiting)) { cFYI(1,("gave up waiting on reconnect in smb_init")); return -EHOSTDOWN; - } /* else "hard" mount - keep retrying until - process is killed or server comes back up */ + } /* else "hard" mount - keep retrying + until process is killed or server + comes back on-line */ } else /* TCP session is reestablished now */ break; @@ -115,23 +117,24 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, simultaneously reconnect the same SMB session */ down(&tcon->ses->sesSem); if(tcon->ses->status == CifsNeedReconnect) - rc = cifs_setup_session(0, tcon->ses, nls_codepage); + rc = cifs_setup_session(0, tcon->ses, + nls_codepage); if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { mark_open_files_invalid(tcon); - rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, - nls_codepage); + rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon + , nls_codepage); up(&tcon->ses->sesSem); if(rc == 0) atomic_inc(&tconInfoReconnectCount); cFYI(1, ("reconnect tcon rc = %d", rc)); /* Removed call to reopen open files here - - it is safer (and faster) to reopen files - one at a time as needed in read and write */ + it is safer (and faster) to reopen files + one at a time as needed in read and write */ /* Check if handle based operation so we - know whether we can continue or not without - returning to caller to reset file handle */ + know whether we can continue or not without + returning to caller to reset file handle */ switch(smb_command) { case SMB_COM_READ_ANDX: case SMB_COM_WRITE_ANDX: @@ -184,20 +187,22 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, if(tcon) { if((tcon->ses) && (tcon->ses->server)){ struct nls_table *nls_codepage; - /* Give Demultiplex thread up to 10 seconds to - reconnect, should be greater than cifs socket - timeout which is 7 seconds */ + /* Give Demultiplex thread up to 10 seconds to + reconnect, should be greater than cifs socket + timeout which is 7 seconds */ while(tcon->ses->server->tcpStatus == CifsNeedReconnect) { wait_event_interruptible_timeout(tcon->ses->server->response_q, (tcon->ses->server->tcpStatus == CifsGood), 10 * HZ); - if(tcon->ses->server->tcpStatus == CifsNeedReconnect) { + if(tcon->ses->server->tcpStatus == + CifsNeedReconnect) { /* on "soft" mounts we wait once */ if((tcon->retry == FALSE) || (tcon->ses->status == CifsExiting)) { cFYI(1,("gave up waiting on reconnect in smb_init")); return -EHOSTDOWN; - } /* else "hard" mount - keep retrying until - process is killed or server comes back up */ + } /* else "hard" mount - keep retrying + until process is killed or server + comes on-line */ } else /* TCP session is reestablished now */ break; @@ -208,23 +213,24 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, simultaneously reconnect the same SMB session */ down(&tcon->ses->sesSem); if(tcon->ses->status == CifsNeedReconnect) - rc = cifs_setup_session(0, tcon->ses, nls_codepage); + rc = cifs_setup_session(0, tcon->ses, + nls_codepage); if(!rc && (tcon->tidStatus == CifsNeedReconnect)) { mark_open_files_invalid(tcon); - rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, - nls_codepage); + rc = CIFSTCon(0, tcon->ses, tcon->treeName, + tcon, nls_codepage); up(&tcon->ses->sesSem); if(rc == 0) atomic_inc(&tconInfoReconnectCount); cFYI(1, ("reconnect tcon rc = %d", rc)); /* Removed call to reopen open files here - - it is safer (and faster) to reopen files - one at a time as needed in read and write */ + it is safer (and faster) to reopen files + one at a time as needed in read and write */ /* Check if handle based operation so we - know whether we can continue or not without - returning to caller to reset file handle */ + know whether we can continue or not without + returning to caller to reset file handle */ switch(smb_command) { case SMB_COM_READ_ANDX: case SMB_COM_WRITE_ANDX: @@ -286,7 +292,8 @@ static int validate_t2(struct smb_t2_rsp * pSMB) if(total_size < 512) { total_size+=le16_to_cpu(pSMB->t2_rsp.DataCount); /* BCC le converted in SendReceive */ - pBCC = (pSMB->hdr.WordCount * 2) + sizeof(struct smb_hdr) + + pBCC = (pSMB->hdr.WordCount * 2) + + sizeof(struct smb_hdr) + (char *)pSMB; if((total_size <= (*(u16 *)pBCC)) && (total_size < @@ -337,8 +344,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) (struct smb_hdr *) pSMBr, &bytes_returned, 0); if (rc == 0) { server->secMode = pSMBr->SecurityMode; - server->secType = NTLM; /* BB override default for NTLMv2 or krb*/ - /* one byte - no need to convert this or EncryptionKeyLen from le,*/ + server->secType = NTLM; /* BB override default for + NTLMv2 or kerberos v5 */ + /* one byte - no need to convert this or EncryptionKeyLen + from little endian */ server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); /* probably no need to store and check maxvcs */ server->maxBuf = @@ -374,7 +383,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) pSMBr->u.extended_response. GUID, 16) != 0) { cFYI(1, - ("UID of server does not match previous connection to same ip address")); + ("UID of server does not match previous connection to same ip address")); memcpy(server-> server_GUID, pSMBr->u. @@ -454,7 +463,8 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) up(&tcon->tconSem); return -EIO; } - rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, (void **)&smb_buffer); + rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, + (void **)&smb_buffer); if (rc) { up(&tcon->tconSem); return rc; @@ -559,7 +569,7 @@ DelFileRetry: PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ + } else { /* BB improve check for buffer overruns BB */ name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->fileName, fileName, name_len); @@ -609,7 +619,7 @@ RmDirRetry: PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ + } else { /* BB improve check for buffer overruns BB */ name_len = strnlen(dirName, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->DirName, dirName, name_len); @@ -657,7 +667,7 @@ MkDirRetry: PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; - } else { /* BB improve the check for buffer overruns BB */ + } else { /* BB improve check for buffer overruns BB */ name_len = strnlen(name, PATH_MAX); name_len++; /* trailing null */ strncpy(pSMB->DirName, name, name_len); @@ -712,7 +722,7 @@ openRetry: name_len++; /* trailing null */ name_len *= 2; pSMB->NameLength = cpu_to_le16(name_len); - } else { /* BB improve the check for buffer overruns BB */ + } else { /* BB improve check for buffer overruns BB */ count = 0; /* no pad */ name_len = strnlen(fileName, PATH_MAX); name_len++; /* trailing null */ @@ -741,7 +751,8 @@ openRetry: pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL); pSMB->CreateDisposition = cpu_to_le32(openDisposition); pSMB->CreateOptions = cpu_to_le32(create_options); - pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); /* BB ??*/ + /* BB Expirement with various impersonation levels and verify */ + pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); pSMB->SecurityFlags = SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY; @@ -755,7 +766,7 @@ openRetry: if (rc) { cFYI(1, ("Error in Open = %d", rc)); } else { - *pOplock = pSMBr->OplockLevel; /* one byte no need to le_to_cpu */ + *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ *netfid = pSMBr->Fid; /* cifs fid stays in le */ /* Let caller know file was created so we can set the mode. */ /* Do we care about the CreateAction in any other cases? */ @@ -2504,7 +2515,9 @@ findFirstRetry: psrch_inf->srch_entries_start = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); - +/* if(le16_to_cpu(pSMBr->t2.DataCount) != le16_to_cpu(pSMBr->t2.TotalDataCount)) { + cERROR(1,("DC: %d TDC: %d",pSMBr->t2.DataCount,pSMBr->t2.TotalDataCount)); +} */ /* BB removeme BB */ parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.ParameterOffset)); @@ -2516,7 +2529,7 @@ findFirstRetry: psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); psrch_inf->index_of_last_entry = psrch_inf->entries_in_buffer; -/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ +/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ /* BB removeme BB */ *pnetfid = parms->SearchHandle; } else { cifs_buf_release(pSMB); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8a8aa785e7b7..d5d49b584db4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -157,9 +157,10 @@ cifs_reconnect(struct TCP_Server_Info *server) qhead); if(mid_entry) { if(mid_entry->midState == MID_REQUEST_SUBMITTED) { - /* Mark other intransit requests as needing retry so - we do not immediately mark the session bad again - (ie after we reconnect below) as they timeout too */ + /* Mark other intransit requests as needing + retry so we do not immediately mark the + session bad again (ie after we reconnect + below) as they timeout too */ mid_entry->midState = MID_RETRY_NEEDED; } } @@ -278,9 +279,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) } else if (length <= 0) { if(server->tcpStatus == CifsNew) { cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); - /* some servers kill tcp session rather than returning - smb negprot error in which case reconnecting here is - not going to help - return error to mount */ + /* some servers kill the TCP session rather than + returning an SMB negprot error, in which + case reconnecting here is not going to help, + and so simply return error to mount */ break; } if(length == -EINTR) { @@ -296,15 +298,19 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) pdu_length = ntohl(smb_buffer->smb_buf_length); /* Only read pdu_length after below checks for too short (due to e.g. int overflow) and too long ie beyond end of buf */ - cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); + cFYI(1,("rfc1002 length(big endian)0x%x)", + pdu_length+4)); temp = (char *) smb_buffer; if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { cFYI(0,("Received 4 byte keep alive packet")); - } else if (temp[0] == (char) RFC1002_POSITIVE_SESSION_RESPONSE) { + } else if (temp[0] == + (char) RFC1002_POSITIVE_SESSION_RESPONSE) { cFYI(1,("Good RFC 1002 session rsp")); - } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { - /* we get this from Windows 98 instead of error on SMB negprot response */ + } else if (temp[0] == + (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { + /* we get this from Windows 98 instead of + an error on SMB negprot response */ cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); if(server->tcpStatus == CifsNew) { /* if nack on negprot (rather than @@ -320,7 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) connected to port 139 (the NACK is since we do not begin with RFC1001 session initialize frame) */ - server->addr.sockAddr.sin_port = htons(CIFS_PORT); + server->addr.sockAddr.sin_port = + htons(CIFS_PORT); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); @@ -333,8 +340,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) csocket = server->ssocket; continue; } else { - if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) - || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { + if((pdu_length > CIFSMaxBufSize + + MAX_CIFS_HDR_SIZE - 4) || + (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { cERROR(1, ("Invalid size SMB length %d and pdu_length %d", length, pdu_length+4)); @@ -377,6 +385,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) continue; } + /* BB FIXME - add checkTrans2SMBSecondary() */ + task_to_wake = NULL; spin_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { @@ -408,7 +418,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) bigbuf = NULL; else smallbuf = NULL; - smb_buffer = NULL; /* will be freed by users thread after he is done */ + smb_buffer = NULL; /* will be freed by users thread after he is done */ wake_up_process(task_to_wake); } else if (is_valid_oplock_break(smb_buffer) == FALSE) { cERROR(1, ("No task to wake, unknown frame rcvd!")); @@ -432,7 +442,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) spin_unlock(&GlobalMid_Lock); /* Although there should not be any requests blocked on this queue it can not hurt to be paranoid and try to wake up requests - that may haven been blocked when more than 50 at time were on the wire + that may haven been blocked when more than 50 at time were on the wire to the same server - they now will see the session is in exit state and get out of SendReceive. */ wake_up_all(&server->request_q); @@ -451,7 +461,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) read_lock(&GlobalSMBSeslock); if (list_empty(&server->pending_mid_q)) { - /* loop through server session structures attached to this and mark them dead */ + /* loop through server session structures attached to this and + mark them dead */ list_for_each(tmp, &GlobalSMBSessionList) { ses = list_entry(tmp, struct cifsSesInfo, @@ -468,7 +479,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) mid_entry = list_entry(tmp, struct mid_q_entry, qhead); if (mid_entry->midState == MID_REQUEST_SUBMITTED) { cFYI(1, - (" Clearing Mid 0x%x - waking up ",mid_entry->mid)); + ("Clearing Mid 0x%x - waking up ",mid_entry->mid)); task_to_wake = mid_entry->tsk; if(task_to_wake) { wake_up_process(task_to_wake); @@ -521,7 +532,8 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* does not have to be a perfect mapping since the field is informational, only used for servers that do not support port 445 and it can be overridden at mount time */ - vol->source_rfc1001_name[i] = toupper(system_utsname.nodename[i]); + vol->source_rfc1001_name[i] = + toupper(system_utsname.nodename[i]); } vol->source_rfc1001_name[15] = 0; @@ -596,14 +608,17 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) /* NB: password legally can have multiple commas and the only illegal character in a password is null */ - if ((value[temp_len] == 0) && (value[temp_len+1] == separator[0])) { + if ((value[temp_len] == 0) && + (value[temp_len+1] == separator[0])) { /* reinsert comma */ value[temp_len] = separator[0]; temp_len+=2; /* move after the second comma */ while(value[temp_len] != 0) { if (value[temp_len] == separator[0]) { - if (value[temp_len+1] == separator[0]) { - temp_len++; /* skip second comma */ + if (value[temp_len+1] == + separator[0]) { + /* skip second comma */ + temp_len++; } else { /* single comma indicating start of next parm */ @@ -629,14 +644,15 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol) } for(i=0,j=0;ipassword[j] = value[i]; - if(value[i] == separator[0] && value[i+1] == separator[0]) { + if(value[i] == separator[0] + && value[i+1] == separator[0]) { /* skip second comma */ i++; } } vol->password[j] = 0; } else { - vol->password = kcalloc(1, temp_len + 1, GFP_KERNEL); + vol->password = kcalloc(1, temp_len+1, GFP_KERNEL); if(vol->password == NULL) { printk("CIFS: no memory for pass\n"); return 1; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 39170cffcad8..22557716f9af 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -409,10 +409,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb) cFYI(1,("new entry %p old entry %p",new_entry,old_entry)); /* validate that new_entry is not past end of SMB */ if(new_entry >= end_of_smb) { - cFYI(1,("search entry %p began after end of SMB %p old entry %p", - new_entry,end_of_smb,old_entry)); + cERROR(1, + ("search entry %p began after end of SMB %p old entry %p", + new_entry, end_of_smb, old_entry)); return NULL; - } else + } else if (new_entry + sizeof(FILE_DIRECTORY_INFO) > end_of_smb) { + cERROR(1,("search entry %p extends after end of SMB %p", + new_entry, end_of_smb)); + return NULL; + } else return new_entry; } -- cgit v1.2.3 From 67010fbc6ff889aaf86592bc148d705c5b9e1a27 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:09 -0700 Subject: [PATCH] cifs: Better handle errors on second socket recv message call Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsglob.h | 3 ++- fs/cifs/connect.c | 31 +++++++++++++++++++++++++------ 2 files changed, 27 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 322a12450ad3..8fc0801f8457 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1,7 +1,7 @@ /* * fs/cifs/cifsglob.h * - * Copyright (C) International Business Machines Corp., 2002,2003 + * Copyright (C) International Business Machines Corp., 2002,2005 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -321,6 +321,7 @@ struct mid_q_entry { __u8 command; /* smb command code */ unsigned multiPart:1; /* multiple responses to one SMB request */ unsigned largeBuf:1; /* if valid response, is pointer to large buf */ + unsigned multiResp:1 /* multiple trans2 responses for one request */ }; struct oplock_q_entry { diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index d5d49b584db4..8c5d310514ea 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -359,20 +359,36 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) length = 0; iov.iov_base = 4 + (char *)smb_buffer; iov.iov_len = pdu_length; - for (total_read = 0; + for (total_read = 0; total_read < pdu_length; total_read += length) { - length = kernel_recvmsg(csocket, &smb_msg, + length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, pdu_length - total_read, 0); - if (length == 0) { + if((server->tcpStatus == CifsExiting) || + (length == -EINTR)) { + /* then will exit */ + goto dmx_loop_end; + } else if (server->tcpStatus == + CifsNeedReconnect) { + cifs_reconnect(server); + csocket = server->ssocket; + /* Reconnect wakes up rspns q */ + /* Now we will reread sock */ + goto dmx_loop_end; + } else if ((length == -ERESTARTSYS) || + (length == -EAGAIN)) { + msleep(1); /* minimum sleep to prevent looping + allowing socket to clear and app threads to set + tcpStatus CifsNeedReconnect if server hung */ + continue; + } else if (length <= 0) { cERROR(1, - ("Zero length receive when expecting %d ", + ("Received no data, expecting %d", pdu_length - total_read)); cifs_reconnect(server); csocket = server->ssocket; - wake_up(&server->response_q); - continue; + goto dmx_loop_end; } } length += 4; /* account for rfc1002 hdr */ @@ -434,6 +450,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) wake_up(&server->response_q); continue; } +dmx_loop_end: + cFYI(1,("Exiting cifsd loop")); + } spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; -- cgit v1.2.3 From 79944bf71352f33f984ac3973b159b5c2cee139d Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:09 -0700 Subject: [PATCH] cifs: missing semicolon from previous fix Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifsglob.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 8fc0801f8457..81babab265e1 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -321,7 +321,7 @@ struct mid_q_entry { __u8 command; /* smb command code */ unsigned multiPart:1; /* multiple responses to one SMB request */ unsigned largeBuf:1; /* if valid response, is pointer to large buf */ - unsigned multiResp:1 /* multiple trans2 responses for one request */ + unsigned multiResp:1; /* multiple trans2 responses for one request */ }; struct oplock_q_entry { -- cgit v1.2.3 From 46810cbf3d951c1ce8ce3311639996ad43ca4ed1 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:09 -0700 Subject: [PATCH] cifs: Ease memory pressure, do not use large buffers in byte range lock requests. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifssmb.c | 8 +- fs/cifs/connect.c | 295 +++++++++++++++++++++++++++--------------------------- 2 files changed, 154 insertions(+), 149 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 834297f7b5e1..a6e66974b286 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -1023,11 +1023,13 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, __u16 count; cFYI(1, ("In CIFSSMBLock - timeout %d numLock %d",waitFlag,numLock)); - rc = smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); + if (rc) return rc; + pSMBr = (LOCK_RSP *)pSMB; /* BB removeme BB */ + if(lockType == LOCKING_ANDX_OPLOCK_RELEASE) { timeout = -1; /* no response expected */ pSMB->Timeout = 0; @@ -1065,7 +1067,7 @@ CIFSSMBLock(const int xid, struct cifsTconInfo *tcon, if (rc) { cFYI(1, ("Send error in Lock = %d", rc)); } - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 8c5d310514ea..419f145c80b5 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -294,165 +294,168 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) csocket = server->ssocket; wake_up(&server->response_q); continue; - } else if (length > 3) { - pdu_length = ntohl(smb_buffer->smb_buf_length); - /* Only read pdu_length after below checks for too short (due - to e.g. int overflow) and too long ie beyond end of buf */ - cFYI(1,("rfc1002 length(big endian)0x%x)", - pdu_length+4)); - - temp = (char *) smb_buffer; - if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { - cFYI(0,("Received 4 byte keep alive packet")); - } else if (temp[0] == - (char) RFC1002_POSITIVE_SESSION_RESPONSE) { - cFYI(1,("Good RFC 1002 session rsp")); - } else if (temp[0] == - (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { - /* we get this from Windows 98 instead of - an error on SMB negprot response */ - cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); - if(server->tcpStatus == CifsNew) { - /* if nack on negprot (rather than - ret of smb negprot error) reconnecting - not going to help, ret error to mount */ - break; - } else { - /* give server a second to - clean up before reconnect attempt */ - msleep(1000); - /* always try 445 first on reconnect - since we get NACK on some if we ever - connected to port 139 (the NACK is - since we do not begin with RFC1001 - session initialize frame) */ - server->addr.sockAddr.sin_port = - htons(CIFS_PORT); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; - } - } else if (temp[0] != (char) 0) { - cERROR(1,("Unknown RFC 1002 frame")); - cifs_dump_mem(" Received Data: ", temp, length); + } else if (length < 4) { + cFYI(1, + ("Frame less than four bytes received %d bytes long.", + length)); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; + } + + /* the right amount was read from socket - 4 bytes */ + + pdu_length = ntohl(smb_buffer->smb_buf_length); + cFYI(1,("rfc1002 length(big endian)0x%x)", pdu_length+4)); + + temp = (char *) smb_buffer; + if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { + cFYI(0,("Received 4 byte keep alive packet")); + } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { + cFYI(1,("Good RFC 1002 session rsp")); + } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { + /* we get this from Windows 98 instead of + an error on SMB negprot response */ + cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); + if(server->tcpStatus == CifsNew) { + /* if nack on negprot (rather than + ret of smb negprot error) reconnecting + not going to help, ret error to mount */ + break; + } else { + /* give server a second to + clean up before reconnect attempt */ + msleep(1000); + /* always try 445 first on reconnect + since we get NACK on some if we ever + connected to port 139 (the NACK is + since we do not begin with RFC1001 + session initialize frame) */ + server->addr.sockAddr.sin_port = + htons(CIFS_PORT); cifs_reconnect(server); csocket = server->ssocket; + wake_up(&server->response_q); continue; - } else { - if((pdu_length > CIFSMaxBufSize + - MAX_CIFS_HDR_SIZE - 4) || - (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { - cERROR(1, - ("Invalid size SMB length %d and pdu_length %d", - length, pdu_length+4)); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; - } else { /* length ok */ - if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { - isLargeBuf = TRUE; - memcpy(bigbuf, smallbuf, 4); - smb_buffer = bigbuf; - } - length = 0; - iov.iov_base = 4 + (char *)smb_buffer; - iov.iov_len = pdu_length; - for (total_read = 0; - total_read < pdu_length; - total_read += length) { - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, - pdu_length - total_read, 0); - if((server->tcpStatus == CifsExiting) || - (length == -EINTR)) { - /* then will exit */ - goto dmx_loop_end; - } else if (server->tcpStatus == - CifsNeedReconnect) { - cifs_reconnect(server); - csocket = server->ssocket; - /* Reconnect wakes up rspns q */ + } + } else if (temp[0] != (char) 0) { + cERROR(1,("Unknown RFC 1002 frame")); + cifs_dump_mem(" Received Data: ", temp, length); + cifs_reconnect(server); + csocket = server->ssocket; + continue; + } else { /* we have an SMB response */ + if((pdu_length > CIFSMaxBufSize + + MAX_CIFS_HDR_SIZE - 4) || + (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { + cERROR(1, + ("Invalid size SMB length %d and pdu_length %d", + length, pdu_length+4)); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; + } else { /* length ok */ + int reconnect = 0; + + if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { + isLargeBuf = TRUE; + memcpy(bigbuf, smallbuf, 4); + smb_buffer = bigbuf; + } + length = 0; + iov.iov_base = 4 + (char *)smb_buffer; + iov.iov_len = pdu_length; + for (total_read = 0; + total_read < pdu_length; + total_read += length) { + length = kernel_recvmsg(csocket, &smb_msg, + &iov, 1, + pdu_length - total_read, 0); + if((server->tcpStatus == CifsExiting) || + (length == -EINTR)) { + /* then will exit */ + reconnect = 2; + break; + } else if (server->tcpStatus == + CifsNeedReconnect) { + cifs_reconnect(server); + csocket = server->ssocket; + /* Reconnect wakes up rspns q */ /* Now we will reread sock */ - goto dmx_loop_end; - } else if ((length == -ERESTARTSYS) || - (length == -EAGAIN)) { - msleep(1); /* minimum sleep to prevent looping - allowing socket to clear and app threads to set - tcpStatus CifsNeedReconnect if server hung */ - continue; - } else if (length <= 0) { - cERROR(1, - ("Received no data, expecting %d", - pdu_length - total_read)); - cifs_reconnect(server); - csocket = server->ssocket; - goto dmx_loop_end; - } + reconnect = 1; + break; + } else if ((length == -ERESTARTSYS) || + (length == -EAGAIN)) { + msleep(1); /* minimum sleep to prevent looping + allowing socket to clear and app threads to set + tcpStatus CifsNeedReconnect if server hung */ + continue; + } else if (length <= 0) { + cERROR(1,("Received no data, expecting %d", + pdu_length - total_read)); + cifs_reconnect(server); + csocket = server->ssocket; + reconnect = 1; + break; } - length += 4; /* account for rfc1002 hdr */ } + if(reconnect == 2) + break; + else if(reconnect == 1) + continue; - dump_smb(smb_buffer, length); - if (checkSMB - (smb_buffer, smb_buffer->Mid, total_read+4)) { - cERROR(1, ("Bad SMB Received ")); - continue; - } + length += 4; /* account for rfc1002 hdr */ + } - /* BB FIXME - add checkTrans2SMBSecondary() */ - - task_to_wake = NULL; - spin_lock(&GlobalMid_Lock); - list_for_each(tmp, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct - mid_q_entry, - qhead); - - if ((mid_entry->mid == smb_buffer->Mid) - && (mid_entry->midState == - MID_REQUEST_SUBMITTED) - && (mid_entry->command == - smb_buffer->Command)) { - cFYI(1,("Found Mid 0x%x wake up" - ,mid_entry->mid)); - task_to_wake = mid_entry->tsk; - mid_entry->resp_buf = - smb_buffer; - mid_entry->midState = - MID_RESPONSE_RECEIVED; - if(isLargeBuf) - mid_entry->largeBuf = 1; - else - mid_entry->largeBuf = 0; - } - } - spin_unlock(&GlobalMid_Lock); - if (task_to_wake) { + dump_smb(smb_buffer, length); + if (checkSMB + (smb_buffer, smb_buffer->Mid, total_read+4)) { + cERROR(1, ("Bad SMB Received ")); + continue; + } + + + task_to_wake = NULL; + spin_lock(&GlobalMid_Lock); + list_for_each(tmp, &server->pending_mid_q) { + mid_entry = list_entry(tmp, struct mid_q_entry, + qhead); + + if ((mid_entry->mid == smb_buffer->Mid) + && (mid_entry->midState == + MID_REQUEST_SUBMITTED) + && (mid_entry->command == + smb_buffer->Command)) { + cFYI(1,("Found Mid 0x%x wake up" + ,mid_entry->mid)); + /* BB FIXME - missing code here BB */ + /* check_2nd_t2(smb_buffer); */ + task_to_wake = mid_entry->tsk; + mid_entry->resp_buf = + smb_buffer; + mid_entry->midState = + MID_RESPONSE_RECEIVED; if(isLargeBuf) - bigbuf = NULL; + mid_entry->largeBuf = 1; else - smallbuf = NULL; - smb_buffer = NULL; /* will be freed by users thread after he is done */ - wake_up_process(task_to_wake); - } else if (is_valid_oplock_break(smb_buffer) == FALSE) { - cERROR(1, ("No task to wake, unknown frame rcvd!")); - cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + mid_entry->largeBuf = 0; } } - } else { - cFYI(1, - ("Frame less than four bytes received %d bytes long.", - length)); - cifs_reconnect(server); - csocket = server->ssocket; - wake_up(&server->response_q); - continue; + spin_unlock(&GlobalMid_Lock); + if (task_to_wake) { + if(isLargeBuf) + bigbuf = NULL; + else + smallbuf = NULL; + smb_buffer = NULL; /* will be freed by users thread after he is done */ + wake_up_process(task_to_wake); + } else if (is_valid_oplock_break(smb_buffer) == FALSE) { + cERROR(1, ("No task to wake, unknown frame rcvd!")); + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + } } -dmx_loop_end: - cFYI(1,("Exiting cifsd loop")); - } spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; -- cgit v1.2.3 From e4eb295d38b57f4d4b956942a48887eb252d97c6 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:09 -0700 Subject: [PATCH] cifs: Handle multiple response transact2 part 1 of 2 Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/cifspdu.h | 2 +- fs/cifs/connect.c | 348 ++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 246 insertions(+), 104 deletions(-) (limited to 'fs') diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index e3e92615705e..aede6a813167 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -330,7 +330,7 @@ struct smb_hdr { }; /* given a pointer to an smb_hdr retrieve the value of byte count */ #define BCC(smb_var) ( *(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) - +#define BCC_LE(smb_var) ( *(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) ) ) /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2* smb_var->WordCount) + 2 ) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 419f145c80b5..a8d592bc33fe 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -116,7 +116,7 @@ cifs_reconnect(struct TCP_Server_Info *server) spin_unlock(&GlobalMid_Lock); server->maxBuf = 0; - cFYI(1, ("Reconnecting tcp session ")); + cFYI(1, ("Reconnecting tcp session")); /* before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they are not used until reconnected */ @@ -194,6 +194,121 @@ cifs_reconnect(struct TCP_Server_Info *server) return rc; } +/* + return codes: + 0 not a transact2, or all data present + >0 transact2 with that much data missing + -EINVAL = invalid transact2 + + */ +static int check2ndT2(struct smb_hdr * pSMB, unsigned int maxBufSize) +{ + struct smb_t2_rsp * pSMBt; + int total_data_size; + int data_in_this_rsp; + int remaining; + + if(pSMB->Command != SMB_COM_TRANSACTION2) + return 0; + + /* check for plausible wct, bcc and t2 data and parm sizes */ + /* check for parm and data offset going beyond end of smb */ + if(pSMB->WordCount != 10) { /* coalesce_t2 depends on this */ + cFYI(1,("invalid transact2 word count")); + return -EINVAL; + } + + pSMBt = (struct smb_t2_rsp *)pSMB; + + total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); + data_in_this_rsp = le16_to_cpu(pSMBt->t2_rsp.DataCount); + + remaining = total_data_size - data_in_this_rsp; + + if(remaining == 0) + return 0; + else if(remaining < 0) { + cFYI(1,("total data %d smaller than data in frame %d", + total_data_size, data_in_this_rsp)); + return -EINVAL; + } else { + cFYI(1,("missing %d bytes from transact2, check next response", + remaining)); + if(total_data_size > maxBufSize) { + cERROR(1,("TotalDataSize %d is over maximum buffer %d", + total_data_size,maxBufSize)); + return -EINVAL; + } + return remaining; + } +} + +static int coalesce_t2(struct smb_hdr * psecond, struct smb_hdr *pTargetSMB) +{ + struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; + struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; + int total_data_size; + int total_in_buf; + int remaining; + int total_in_buf2; + char * data_area_of_target; + char * data_area_of_buf2; + __u16 byte_count; + + total_data_size = le16_to_cpu(pSMBt->t2_rsp.TotalDataCount); + + if(total_data_size != le16_to_cpu(pSMB2->t2_rsp.TotalDataCount)) { + cFYI(1,("total data sizes of primary and secondary t2 differ")); + } + + total_in_buf = le16_to_cpu(pSMBt->t2_rsp.DataCount); + + remaining = total_data_size - total_in_buf; + + if(remaining < 0) + return -EINVAL; + + if(remaining == 0) /* nothing to do, ignore */ + return 0; + + total_in_buf2 = le16_to_cpu(pSMB2->t2_rsp.DataCount); + if(remaining < total_in_buf2) { + cFYI(1,("transact2 2nd response contains too much data")); + } + + /* find end of first SMB data area */ + data_area_of_target = (char *)&pSMBt->hdr.Protocol + + le16_to_cpu(pSMBt->t2_rsp.DataOffset); + /* validate target area */ + + data_area_of_buf2 = (char *) &pSMB2->hdr.Protocol + + le16_to_cpu(pSMB2->t2_rsp.DataOffset); + + data_area_of_target += total_in_buf; + + /* copy second buffer into end of first buffer */ + memcpy(data_area_of_target,data_area_of_buf2,total_in_buf2); + total_in_buf += total_in_buf2; + pSMBt->t2_rsp.DataCount = cpu_to_le16(total_in_buf); + byte_count = le16_to_cpu(BCC_LE(pTargetSMB)); + byte_count += total_in_buf2; + BCC_LE(pTargetSMB) = cpu_to_le16(byte_count); + + byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); + byte_count += total_in_buf2; + + /* BB also add check that we are not beyond maximum buffer size */ + + pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); + + if(remaining == total_in_buf2) { + cFYI(1,("found the last secondary response")); + return 0; /* we are done */ + } else /* more responses to go */ + return 1; + +} + static int cifs_demultiplex_thread(struct TCP_Server_Info *server) { @@ -211,6 +326,8 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) struct mid_q_entry *mid_entry; char *temp; int isLargeBuf = FALSE; + int isMultiRsp; + int reconnect; daemonize("cifsd"); allow_signal(SIGKILL); @@ -254,6 +371,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) memset(smallbuf, 0, sizeof (struct smb_hdr)); isLargeBuf = FALSE; + isMultiRsp = FALSE; smb_buffer = smallbuf; iov.iov_base = smb_buffer; iov.iov_len = 4; @@ -311,13 +429,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) temp = (char *) smb_buffer; if (temp[0] == (char) RFC1002_SESSION_KEEP_ALIVE) { - cFYI(0,("Received 4 byte keep alive packet")); + continue; } else if (temp[0] == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { - cFYI(1,("Good RFC 1002 session rsp")); + cFYI(1,("Good RFC 1002 session rsp")); + continue; } else if (temp[0] == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { /* we get this from Windows 98 instead of an error on SMB negprot response */ - cFYI(1,("Negative RFC 1002 Session Response Error 0x%x)",temp[4])); + cFYI(1,("Negative RFC1002 Session Response Error 0x%x)", + temp[4])); if(server->tcpStatus == CifsNew) { /* if nack on negprot (rather than ret of smb negprot error) reconnecting @@ -345,118 +465,140 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) cifs_reconnect(server); csocket = server->ssocket; continue; - } else { /* we have an SMB response */ - if((pdu_length > CIFSMaxBufSize + - MAX_CIFS_HDR_SIZE - 4) || + } + + /* else we have an SMB response */ + if((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || (pdu_length < sizeof (struct smb_hdr) - 1 - 4)) { - cERROR(1, - ("Invalid size SMB length %d and pdu_length %d", + cERROR(1, ("Invalid size SMB length %d pdu_length %d", length, pdu_length+4)); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; + } + + /* else length ok */ + reconnect = 0; + + if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { + isLargeBuf = TRUE; + memcpy(bigbuf, smallbuf, 4); + smb_buffer = bigbuf; + } + length = 0; + iov.iov_base = 4 + (char *)smb_buffer; + iov.iov_len = pdu_length; + for (total_read = 0; total_read < pdu_length; + total_read += length) { + length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, + pdu_length - total_read, 0); + if((server->tcpStatus == CifsExiting) || + (length == -EINTR)) { + /* then will exit */ + reconnect = 2; + break; + } else if (server->tcpStatus == CifsNeedReconnect) { cifs_reconnect(server); csocket = server->ssocket; - wake_up(&server->response_q); + /* Reconnect wakes up rspns q */ + /* Now we will reread sock */ + reconnect = 1; + break; + } else if ((length == -ERESTARTSYS) || + (length == -EAGAIN)) { + msleep(1); /* minimum sleep to prevent looping, + allowing socket to clear and app + threads to set tcpStatus + CifsNeedReconnect if server hung*/ continue; - } else { /* length ok */ - int reconnect = 0; - - if(pdu_length > MAX_CIFS_HDR_SIZE - 4) { - isLargeBuf = TRUE; - memcpy(bigbuf, smallbuf, 4); - smb_buffer = bigbuf; - } - length = 0; - iov.iov_base = 4 + (char *)smb_buffer; - iov.iov_len = pdu_length; - for (total_read = 0; - total_read < pdu_length; - total_read += length) { - length = kernel_recvmsg(csocket, &smb_msg, - &iov, 1, - pdu_length - total_read, 0); - if((server->tcpStatus == CifsExiting) || - (length == -EINTR)) { - /* then will exit */ - reconnect = 2; - break; - } else if (server->tcpStatus == - CifsNeedReconnect) { - cifs_reconnect(server); - csocket = server->ssocket; - /* Reconnect wakes up rspns q */ - /* Now we will reread sock */ - reconnect = 1; - break; - } else if ((length == -ERESTARTSYS) || - (length == -EAGAIN)) { - msleep(1); /* minimum sleep to prevent looping - allowing socket to clear and app threads to set - tcpStatus CifsNeedReconnect if server hung */ - continue; - } else if (length <= 0) { - cERROR(1,("Received no data, expecting %d", - pdu_length - total_read)); - cifs_reconnect(server); - csocket = server->ssocket; - reconnect = 1; - break; - } - } - if(reconnect == 2) - break; - else if(reconnect == 1) - continue; - - length += 4; /* account for rfc1002 hdr */ + } else if (length <= 0) { + cERROR(1,("Received no data, expecting %d", + pdu_length - total_read)); + cifs_reconnect(server); + csocket = server->ssocket; + reconnect = 1; + break; } + } + if(reconnect == 2) + break; + else if(reconnect == 1) + continue; - dump_smb(smb_buffer, length); - if (checkSMB - (smb_buffer, smb_buffer->Mid, total_read+4)) { - cERROR(1, ("Bad SMB Received ")); - continue; - } + length += 4; /* account for rfc1002 hdr */ + + dump_smb(smb_buffer, length); + if (checkSMB (smb_buffer, smb_buffer->Mid, total_read+4)) { + cERROR(1, ("Bad SMB Received ")); + continue; + } - task_to_wake = NULL; - spin_lock(&GlobalMid_Lock); - list_for_each(tmp, &server->pending_mid_q) { - mid_entry = list_entry(tmp, struct mid_q_entry, - qhead); - - if ((mid_entry->mid == smb_buffer->Mid) - && (mid_entry->midState == - MID_REQUEST_SUBMITTED) - && (mid_entry->command == - smb_buffer->Command)) { - cFYI(1,("Found Mid 0x%x wake up" - ,mid_entry->mid)); - /* BB FIXME - missing code here BB */ - /* check_2nd_t2(smb_buffer); */ - task_to_wake = mid_entry->tsk; - mid_entry->resp_buf = - smb_buffer; - mid_entry->midState = - MID_RESPONSE_RECEIVED; - if(isLargeBuf) - mid_entry->largeBuf = 1; - else - mid_entry->largeBuf = 0; - } - } - spin_unlock(&GlobalMid_Lock); - if (task_to_wake) { + + task_to_wake = NULL; + spin_lock(&GlobalMid_Lock); + list_for_each(tmp, &server->pending_mid_q) { + mid_entry = list_entry(tmp, struct mid_q_entry, qhead); + + if ((mid_entry->mid == smb_buffer->Mid) && + (mid_entry->midState == MID_REQUEST_SUBMITTED) && + (mid_entry->command == smb_buffer->Command)) { + cFYI(1,("Found Mid 0x%x wake", mid_entry->mid)); + + if(check2ndT2(smb_buffer,server->maxBuf) > 0) { + /* We have a multipart transact2 resp */ + if(mid_entry->resp_buf) { + /* merge response - fix up 1st*/ + if(coalesce_t2(smb_buffer, + mid_entry->resp_buf)) { + isMultiRsp = TRUE; + break; + } else { + /* all parts received */ + goto multi_t2_fnd; + } + } else { + if(!isLargeBuf) { + cERROR(1,("1st trans2 resp needs bigbuf")); + /* BB maybe we can fix this up, switch + to already allocated large buffer? */ + } else { + mid_entry->resp_buf = + smb_buffer; + mid_entry->largeBuf = 1; + isMultiRsp = TRUE; + bigbuf = NULL; + } + } + break; + } + mid_entry->resp_buf = smb_buffer; if(isLargeBuf) - bigbuf = NULL; + mid_entry->largeBuf = 1; else - smallbuf = NULL; - smb_buffer = NULL; /* will be freed by users thread after he is done */ - wake_up_process(task_to_wake); - } else if (is_valid_oplock_break(smb_buffer) == FALSE) { - cERROR(1, ("No task to wake, unknown frame rcvd!")); - cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + mid_entry->largeBuf = 0; +multi_t2_fnd: + task_to_wake = mid_entry->tsk; + mid_entry->midState = MID_RESPONSE_RECEIVED; + break; } } - } + spin_unlock(&GlobalMid_Lock); + if (task_to_wake) { + if(isLargeBuf) + bigbuf = NULL; + else + smallbuf = NULL; + /* smb buffer freed by user thread when done */ + wake_up_process(task_to_wake); + } else if ((is_valid_oplock_break(smb_buffer) == FALSE) + && (isMultiRsp == FALSE)) { + cERROR(1, ("No task to wake, unknown frame rcvd!")); + cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); + } + } /* end while !EXITING */ + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; server->tsk = NULL; -- cgit v1.2.3 From 275cde1a1f3880601509c851d72c82bb8d3ee67c Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:10 -0700 Subject: [PATCH] cifs: cleanup various long lines Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/transport.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index f9e16b39898c..79bf686a2a19 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -41,7 +41,7 @@ AllocMidQEntry(struct smb_hdr *smb_buffer, struct cifsSesInfo *ses) struct mid_q_entry *temp; if (ses == NULL) { - cERROR(1, ("Null session passed in to AllocMidQEntry ")); + cERROR(1, ("Null session passed in to AllocMidQEntry")); return NULL; } if (ses->server == NULL) { @@ -185,7 +185,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, int smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, - unsigned int smb_buf_length, struct kvec * write_vector /* page list */, struct sockaddr *sin) + unsigned int smb_buf_length, struct kvec * write_vector + /* page list */, struct sockaddr *sin) { int rc = 0; int i = 0; @@ -215,7 +216,8 @@ smb_sendv(struct socket *ssocket, struct smb_hdr *smb_buffer, dump_smb(smb_buffer, len); while (len > 0) { - rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, len?); + rc = kernel_sendmsg(ssocket, &smb_msg, &iov, number_of_pages, + len); if ((rc == -ENOSPC) || (rc == -EAGAIN)) { i++; if(i > 60) { @@ -351,8 +353,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, rc = cifs_sign_smb(in_buf, ses->server, &midQ->sequence_number); midQ->midState = MID_REQUEST_SUBMITTED; -/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, piovec, - (struct sockaddr *) &(ses->server->addr.sockAddr));*/ +/* rc = smb_sendv(ses->server->ssocket, in_buf, in_buf->smb_buf_length, + piovec, + (struct sockaddr *) &(ses->server->addr.sockAddr));*/ if(rc < 0) { DeleteMidQEntry(midQ); up(&ses->server->tcpSem); @@ -407,7 +410,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, } else { spin_lock(&GlobalMid_Lock); while(1) { - if(atomic_read(&ses->server->inFlight) >= cifs_max_pending){ + if(atomic_read(&ses->server->inFlight) >= + cifs_max_pending){ spin_unlock(&GlobalMid_Lock); wait_event(ses->server->request_q, atomic_read(&ses->server->inFlight) @@ -495,7 +499,7 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, up(&ses->server->tcpSem); if (long_op == -1) goto cifs_no_response_exit; - else if (long_op == 2) /* writes past end of file can take looooong time */ + else if (long_op == 2) /* writes past end of file can take loong time */ timeout = 300 * HZ; else if (long_op == 1) timeout = 45 * HZ; /* should be greater than @@ -582,8 +586,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, ses->server->mac_signing_key, midQ->sequence_number+1); if(rc) { - cERROR(1,("Unexpected packet signature received from server")); - /* BB FIXME - add code to kill session here */ + cERROR(1,("Unexpected SMB signature")); + /* BB FIXME add code to kill session */ } } -- cgit v1.2.3 From cd63499cbe37e53e6cc084c8a35d911a4613c797 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:10 -0700 Subject: [PATCH] cifs: Handle case of multiple trans2 responses for one SMB request (part 2 of 2) Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 2 ++ fs/cifs/cifssmb.c | 22 +++++++++++----------- fs/cifs/connect.c | 19 ++++++++++--------- 3 files changed, 23 insertions(+), 20 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 0414eb325468..3d61d96d7407 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -4,6 +4,8 @@ Fix caching problem, in which readdir of directory containing a file which was cached could cause the file's time stamp to be updated without invalidating the readahead data (so we could get stale file data on the client for that file even as the server copy changed). +Cleanup response processing so cifsd can not loop when abnormally +terminated. Version 1.32 diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index a6e66974b286..f8edf816b4be 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -470,7 +470,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) return rc; } else { smb_buffer_response = smb_buffer; /* BB removeme BB */ - } + } rc = SendReceive(xid, tcon->ses, smb_buffer, smb_buffer_response, &length, 0); if (rc) @@ -2517,9 +2517,6 @@ findFirstRetry: psrch_inf->srch_entries_start = (char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.DataOffset); -/* if(le16_to_cpu(pSMBr->t2.DataCount) != le16_to_cpu(pSMBr->t2.TotalDataCount)) { - cERROR(1,("DC: %d TDC: %d",pSMBr->t2.DataCount,pSMBr->t2.TotalDataCount)); -} */ /* BB removeme BB */ parms = (T2_FFIRST_RSP_PARMS *)((char *) &pSMBr->hdr.Protocol + le16_to_cpu(pSMBr->t2.ParameterOffset)); @@ -2531,7 +2528,6 @@ findFirstRetry: psrch_inf->entries_in_buffer = le16_to_cpu(parms->SearchCount); psrch_inf->index_of_last_entry = psrch_inf->entries_in_buffer; -/*cFYI(1,("entries in buf %d index_of_last %d",psrch_inf->entries_in_buffer,psrch_inf->index_of_last_entry)); */ /* BB removeme BB */ *pnetfid = parms->SearchHandle; } else { cifs_buf_release(pSMB); @@ -3451,11 +3447,13 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, cFYI(1, ("SetFileSize (via SetFileInfo) %lld", (long long)size)); - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + if (rc) return rc; + pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; + pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); @@ -3515,7 +3513,7 @@ CIFSSMBSetFileSize(const int xid, struct cifsTconInfo *tcon, __u64 size, } if (pSMB) - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ @@ -3541,11 +3539,13 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I __u16 params, param_offset, offset, byte_count, count; cFYI(1, ("Set Times (via SetFileInfo)")); - rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, - (void **) &pSMBr); + rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); + if (rc) return rc; + pSMBr = (struct smb_com_transaction2_sfi_rsp *)pSMB; + /* At this point there is no need to override the current pid with the pid of the opener, but that could change if we someday use an existing handle (rather than opening one on the fly) */ @@ -3591,7 +3591,7 @@ CIFSSMBSetFileTimes(const int xid, struct cifsTconInfo *tcon, const FILE_BASIC_I cFYI(1,("Send error in Set Time (SetFileInfo) = %d",rc)); } - cifs_buf_release(pSMB); + cifs_small_buf_release(pSMB); /* Note: On -EAGAIN error only caller can retry on handle based calls since file handle passed in no longer valid */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a8d592bc33fe..e3b177a90b37 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -544,15 +544,13 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) if ((mid_entry->mid == smb_buffer->Mid) && (mid_entry->midState == MID_REQUEST_SUBMITTED) && (mid_entry->command == smb_buffer->Command)) { - cFYI(1,("Found Mid 0x%x wake", mid_entry->mid)); - if(check2ndT2(smb_buffer,server->maxBuf) > 0) { /* We have a multipart transact2 resp */ + isMultiRsp = TRUE; if(mid_entry->resp_buf) { /* merge response - fix up 1st*/ if(coalesce_t2(smb_buffer, mid_entry->resp_buf)) { - isMultiRsp = TRUE; break; } else { /* all parts received */ @@ -564,10 +562,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) /* BB maybe we can fix this up, switch to already allocated large buffer? */ } else { + /* Have first buffer */ mid_entry->resp_buf = smb_buffer; mid_entry->largeBuf = 1; - isMultiRsp = TRUE; bigbuf = NULL; } } @@ -586,11 +584,14 @@ multi_t2_fnd: } spin_unlock(&GlobalMid_Lock); if (task_to_wake) { - if(isLargeBuf) - bigbuf = NULL; - else - smallbuf = NULL; - /* smb buffer freed by user thread when done */ + /* Was previous buf put in mpx struct for multi-rsp? */ + if(!isMultiRsp) { + /* smb buffer will be freed by user thread */ + if(isLargeBuf) { + bigbuf = NULL; + } else + smallbuf = NULL; + } wake_up_process(task_to_wake); } else if ((is_valid_oplock_break(smb_buffer) == FALSE) && (isMultiRsp == FALSE)) { -- cgit v1.2.3 From 11aa0149d0e49ee1791735ec4ae3079b27b9a68e Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:10 -0700 Subject: [PATCH] cifs: Fix mapping of EMLINK case Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 4 ++++ fs/cifs/cifsfs.h | 2 +- fs/cifs/netmisc.c | 3 ++- fs/cifs/smberr.h | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 3d61d96d7407..21a246473a91 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,3 +1,7 @@ +Version 1.34 +------------ +Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. + Version 1.33 ------------ Fix caching problem, in which readdir of directory containing a file diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 8f742796a627..d00b3bfe1a52 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -96,5 +96,5 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern int cifs_ioctl (struct inode * inode, struct file * filep, unsigned int command, unsigned long arg); -#define CIFS_VERSION "1.33" +#define CIFS_VERSION "1.34" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index dfaabc8d8fb6..a92af41d4411 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -78,6 +78,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = { {ErrQuota, -EDQUOT}, {ErrNotALink, -ENOLINK}, {ERRnetlogonNotStarted,-ENOPROTOOPT}, + {ErrTooManyLinks,-EMLINK}, {0, 0} }; @@ -742,7 +743,7 @@ static const struct { ERRDOS, 182, NT_STATUS_DRIVER_ORDINAL_NOT_FOUND}, { ERRDOS, 127, NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND}, { ERRDOS, 288, NT_STATUS_RESOURCE_NOT_OWNED}, { - ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LINKS}, { + ERRDOS, ErrTooManyLinks, NT_STATUS_TOO_MANY_LINKS}, { ERRHRD, ERRgeneral, NT_STATUS_QUOTA_LIST_INCONSISTENT}, { ERRHRD, ERRgeneral, NT_STATUS_FILE_IS_OFFLINE}, { ERRDOS, 21, 0xc000026e}, { diff --git a/fs/cifs/smberr.h b/fs/cifs/smberr.h index 1b53dcd0f2eb..cd41c67ff8d3 100644 --- a/fs/cifs/smberr.h +++ b/fs/cifs/smberr.h @@ -107,6 +107,10 @@ #define ErrNotALink 0x201 /* A link operation was performed on a pathname that was not a link. */ +/* Below errors are used internally (do not come over the wire) for passthrough + from STATUS codes to POSIX only */ +#define ErrTooManyLinks 0xFFFE + /* Following error codes may be generated with the ERRSRV error class.*/ #define ERRerror 1 /* Non-specific error code. It is -- cgit v1.2.3 From 57337e42f1393941d59d5154eed27a63988ff2be Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:10 -0700 Subject: [PATCH] cifs: handle termination of cifs oplockd kernel thread Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 1 + fs/cifs/cifsfs.c | 1 + fs/cifs/connect.c | 11 ++++++----- fs/cifs/misc.c | 25 +++++++++++++++---------- 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 21a246473a91..bd3b55e1be17 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,6 +1,7 @@ Version 1.34 ------------ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. +Do not oops if user kills cifs oplock kernel thread. Version 1.33 ------------ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 6322aada491f..8cc23e7d0d5d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -835,6 +835,7 @@ static int cifs_oplock_thread(void * dummyarg) } } while(!signal_pending(current)); complete_and_exit (&cifs_oplock_exited, 0); + oplockThread = NULL; } static int __init diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e3b177a90b37..437be1efe99e 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -384,7 +384,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) if(server->tcpStatus == CifsExiting) { break; } else if (server->tcpStatus == CifsNeedReconnect) { - cFYI(1,("Reconnecting after server stopped responding")); + cFYI(1,("Reconnect after server stopped responding")); cifs_reconnect(server); cFYI(1,("call to reconnect done")); csocket = server->ssocket; @@ -396,7 +396,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) continue; } else if (length <= 0) { if(server->tcpStatus == CifsNew) { - cFYI(1,("tcp session abended prematurely (after SMBnegprot)")); + cFYI(1,("tcp session abend after SMBnegprot")); /* some servers kill the TCP session rather than returning an SMB negprot error, in which case reconnecting here is not going to help, @@ -407,14 +407,15 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server) cFYI(1,("cifsd thread killed")); break; } - cFYI(1,("Reconnecting after unexpected peek error %d",length)); + cFYI(1,("Reconnect after unexpected peek error %d", + length)); cifs_reconnect(server); csocket = server->ssocket; wake_up(&server->response_q); continue; } else if (length < 4) { cFYI(1, - ("Frame less than four bytes received %d bytes long.", + ("Frame under four bytes received (%d bytes long)", length)); cifs_reconnect(server); csocket = server->ssocket; @@ -593,7 +594,7 @@ multi_t2_fnd: smallbuf = NULL; } wake_up_process(task_to_wake); - } else if ((is_valid_oplock_break(smb_buffer) == FALSE) + } else if ((is_valid_oplock_break(smb_buffer) == FALSE) && (isMultiRsp == FALSE)) { cERROR(1, ("No task to wake, unknown frame rcvd!")); cifs_dump_mem("Received Data is: ",temp,sizeof(struct smb_hdr)); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 75fd3bd6e233..db14b503d89e 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -452,25 +452,30 @@ is_valid_oplock_break(struct smb_hdr *buf) atomic_inc(&tcon->num_oplock_brks); #endif list_for_each(tmp1,&tcon->openFileList){ - netfile = list_entry(tmp1,struct cifsFileInfo,tlist); + netfile = list_entry(tmp1,struct cifsFileInfo, + tlist); if(pSMB->Fid == netfile->netfid) { struct cifsInodeInfo *pCifsInode; read_unlock(&GlobalSMBSeslock); - cFYI(1,("Matching file id, processing oplock break")); + cFYI(1,("file id match, oplock break")); pCifsInode = CIFS_I(netfile->pInode); pCifsInode->clientCanCacheAll = FALSE; if(pSMB->OplockLevel == 0) - pCifsInode->clientCanCacheRead = FALSE; + pCifsInode->clientCanCacheRead + = FALSE; pCifsInode->oplockPending = TRUE; - AllocOplockQEntry(netfile->pInode, netfile->netfid, tcon); + AllocOplockQEntry(netfile->pInode, + netfile->netfid, + tcon); cFYI(1,("about to wake up oplock thd")); - wake_up_process(oplockThread); + if(oplockThread) + wake_up_process(oplockThread); return TRUE; } } read_unlock(&GlobalSMBSeslock); - cFYI(1,("No matching file for oplock break on connection")); + cFYI(1,("No matching file for oplock break")); return TRUE; } } @@ -491,7 +496,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) buffer = (unsigned char *) smb_buf; for (i = 0, j = 0; i < smb_buf_length; i++, j++) { - if (i % 8 == 0) { /* we have reached the beginning of line */ + if (i % 8 == 0) { /* have reached the beginning of line */ printk(KERN_DEBUG "| "); j = 0; } @@ -502,7 +507,7 @@ dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) else debug_line[1 + (2 * j)] = '_'; - if (i % 8 == 7) { /* we have reached end of line, time to print ascii */ + if (i % 8 == 7) { /* reached end of line, time to print ascii */ debug_line[16] = 0; printk(" | %s\n", debug_line); } @@ -577,7 +582,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen, } } j++; - /* check to make sure we do not overrun callers allocated temp buffer */ + /* make sure we do not overrun callers allocated temp buffer */ if(j >= (2 * NAME_MAX)) break; } @@ -599,7 +604,7 @@ cifsConvertToUCS(__le16 * target, const char *source, int maxlen, char src_char; if(!mapChars) - return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); + return cifs_strtoUCS((wchar_t *) target, source, PATH_MAX, cp); for(i = 0, j = 0; i < maxlen; j++) { src_char = source[i]; -- cgit v1.2.3 From 31ca3bc3c569f9fe02aae6974ac3a9126f14902f Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:11 -0700 Subject: [PATCH] cifs: Do not init smb requests or block when sending requests if cifsd thread is no longer running to demultixplex responses. Do not send FindClose request when FindFirst failed without reaching end of search. Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 5 ++++- fs/cifs/cifssmb.c | 6 ++++-- fs/cifs/connect.c | 40 +++++++++++++++++++++++++++++++++++++--- fs/cifs/file.c | 3 ++- fs/cifs/transport.c | 6 ++++++ 5 files changed, 53 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index bd3b55e1be17..4d2404305ab6 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,7 +1,10 @@ Version 1.34 ------------ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. -Do not oops if user kills cifs oplock kernel thread. +Do not oops if root user kills cifs oplock kernel thread or +kills the cifsd thread (NB: killing the cifs kernel threads is not +recommended, unmount and rmmod cifs will kill them when they are +no longer needed). Version 1.33 ------------ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f8edf816b4be..b004fef0a42b 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -90,7 +90,8 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, check for tcp and smb session status done differently for those three - in the calling routine */ if(tcon) { - if((tcon->ses) && (tcon->ses->server)){ + if((tcon->ses) && (tcon->ses->status != CifsExiting) && + (tcon->ses->server)){ struct nls_table *nls_codepage; /* Give Demultiplex thread up to 10 seconds to reconnect, should be greater than cifs socket @@ -185,7 +186,8 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, check for tcp and smb session status done differently for those three - in the calling routine */ if(tcon) { - if((tcon->ses) && (tcon->ses->server)){ + if((tcon->ses) && (tcon->ses->status != CifsExiting) && + (tcon->ses->server)){ struct nls_table *nls_codepage; /* Give Demultiplex thread up to 10 seconds to reconnect, should be greater than cifs socket diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 437be1efe99e..ac1f970e5369 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -604,7 +604,13 @@ multi_t2_fnd: spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; server->tsk = NULL; - atomic_set(&server->inFlight, 0); + /* check if we have blocked requests that need to free */ + /* Note that cifs_max_pending is normally 50, but + can be set at module install time to as little as two */ + if(atomic_read(&server->inFlight) >= cifs_max_pending) + atomic_set(&server->inFlight, cifs_max_pending - 1); + /* We do not want to set the max_pending too low or we + could end up with the counter going negative */ spin_unlock(&GlobalMid_Lock); /* Although there should not be any requests blocked on this queue it can not hurt to be paranoid and try to wake up requests @@ -640,6 +646,17 @@ multi_t2_fnd: } read_unlock(&GlobalSMBSeslock); } else { + /* although we can not zero the server struct pointer yet, + since there are active requests which may depnd on them, + mark the corresponding SMB sessions as exiting too */ + list_for_each(tmp, &GlobalSMBSessionList) { + ses = list_entry(tmp, struct cifsSesInfo, + cifsSessionList); + if (ses->server == server) { + ses->status = CifsExiting; + } + } + spin_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); @@ -661,17 +678,34 @@ multi_t2_fnd: if (list_empty(&server->pending_mid_q)) { /* mpx threads have not exited yet give them at least the smb send timeout time for long ops */ + /* due to delays on oplock break requests, we need + to wait at least 45 seconds before giving up + on a request getting a response and going ahead + and killing cifsd */ cFYI(1, ("Wait for exit from demultiplex thread")); - msleep(46); + msleep(46000); /* if threads still have not exited they are probably never coming home not much else we can do but free the memory */ } - kfree(server); write_lock(&GlobalSMBSeslock); atomic_dec(&tcpSesAllocCount); length = tcpSesAllocCount.counter; + + /* last chance to mark ses pointers invalid + if there are any pointing to this (e.g + if a crazy root user tried to kill cifsd + kernel thread explicitly this might happen) */ + list_for_each(tmp, &GlobalSMBSessionList) { + ses = list_entry(tmp, struct cifsSesInfo, + cifsSessionList); + if (ses->server == server) { + ses->server = NULL; + } + } write_unlock(&GlobalSMBSeslock); + + kfree(server); if(length > 0) { mempool_resize(cifs_req_poolp, length + cifs_min_rcv, diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1df26ddf68b1..dde2d251fc3d 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -512,7 +512,8 @@ int cifs_closedir(struct inode *inode, struct file *file) pTcon = cifs_sb->tcon; cFYI(1, ("Freeing private data in close dir")); - if (pCFileStruct->srch_inf.endOfSearch == FALSE) { + if ((pCFileStruct->srch_inf.endOfSearch == FALSE) && + (pCFileStruct->invalidHandle == FALSE)) { pCFileStruct->invalidHandle = TRUE; rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid); cFYI(1, ("Closing uncompleted readdir with rc %d", diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 79bf686a2a19..0046c219833d 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -270,6 +270,9 @@ CIFSSendRcv(const unsigned int xid, struct cifsSesInfo *ses, + if(ses->server->tcpStatus == CIFS_EXITING) + return -ENOENT; + /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ @@ -401,6 +404,9 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, return -EIO; } + if(ses->server->tcpStatus == CifsExiting) + return -ENOENT; + /* Ensure that we do not send more than 50 overlapping requests to the same server. We may make this configurable later or use ses->maxReq */ -- cgit v1.2.3 From 0cb766ae629c70d53040f85de73db0583eadb233 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 28 Apr 2005 22:41:11 -0700 Subject: [PATCH] cifs: Do not sleep interruptible after socket connect failure .. since it can be due to pending kill. Update readme information to better describe cifs umount Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/README | 15 ++++++++++----- fs/cifs/connect.c | 3 +-- 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/cifs/README b/fs/cifs/README index bec7b3fc8a72..7b4ac096cd11 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -101,12 +101,15 @@ Allowing User Unmounts ====================== To permit users to ummount directories that they have user mounted (see above), the utility umount.cifs may be used. It may be invoked directly, or if -umount.cifs is placed in /sbin, umount -i can invoke the cifs umount helper +umount.cifs is placed in /sbin, umount can invoke the cifs umount helper (at least for most versions of the umount utility) for umount of cifs -mounts. As with mount.cifs, to enable user unmounts umount.cifs must be marked -as suid (e.g. "chmod +s /sbin/umount.cifs"). For this utility to succeed -the target path must be a cifs mount, and the uid of the current user must -match the uid of the user who mounted the resource. +mounts, unless umount is invoked with -i (which will avoid invoking a umount +helper). As with mount.cifs, to enable user unmounts umount.cifs must be marked +as suid (e.g. "chmod +s /sbin/umount.cifs") or equivalent (some distributions +allow adding entries to a file to the /etc/permissions file to achieve the +equivalent suid effect). For this utility to succeed the target path +must be a cifs mount, and the uid of the current user must match the uid +of the user who mounted the resource. Also note that the customary way of allowing user mounts and unmounts is (instead of using mount.cifs and unmount.cifs as suid) to add a line @@ -404,6 +407,8 @@ A partial list of the supported mount options follows: This has no effect if the server does not support Unicode on the wire. nomapchars Do not translate any of these seven characters (default). + remount remount the share (often used to change from ro to rw mounts + or vice versa) The mount.cifs mount helper also accepts a few mount options before -o including: diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index ac1f970e5369..e568cc47a7f9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -178,8 +178,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->workstation_RFC1001_name); } if(rc) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(3 * HZ); + msleep(3000); } else { atomic_inc(&tcpSesReconnectCount); spin_lock(&GlobalMid_Lock); -- cgit v1.2.3 From ea3834d9fb348fb1144ad3affea22df933eaf62e Mon Sep 17 00:00:00 2001 From: Prasanna Meda Date: Fri, 29 Apr 2005 16:00:17 +0100 Subject: namei: add audit_inode to all branches in path_lookup Main change is in path_lookup: added a goto to do audit_inode instead of return statement, when emul_lookup_dentry for root is successful.The existing code does audit_inode only when lookup is done in normal root or cwd. Other changes: Some lookup routines are returning zero on success, and some are returning zero on failure. I documented the related function signatures in this code path, so that one can glance over abstract functions without understanding the entire code. Signed-off-by: Prasanna Meda Signed-off-by: David Woodhouse --- fs/namei.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/namei.c b/fs/namei.c index 9e4aef2a1a21..0f76fd75591b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -686,11 +686,11 @@ fail: /* * Name resolution. + * This is the basic name resolution function, turning a pathname into + * the final dentry. We expect 'base' to be positive and a directory. * - * This is the basic name resolution function, turning a pathname - * into the final dentry. - * - * We expect 'base' to be positive and a directory. + * Returns 0 and nd will have valid dentry and mnt on success. + * Returns error and drops reference to input namei data on failure. */ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) { @@ -929,8 +929,10 @@ int fastcall path_walk(const char * name, struct nameidata *nd) return link_path_walk(name, nd); } -/* SMP-safe */ -/* returns 1 if everything is done */ +/* + * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if + * everything is done. Returns 0 and drops input nd, if lookup failed; + */ static int __emul_lookup_dentry(const char *name, struct nameidata *nd) { if (path_walk(name, nd)) @@ -994,9 +996,10 @@ set_it: } } +/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd) { - int retval; + int retval = 0; nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->flags = flags; @@ -1009,7 +1012,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata nd->dentry = dget(current->fs->altroot); read_unlock(¤t->fs->lock); if (__emul_lookup_dentry(name,nd)) - return 0; + goto out; /* found in altroot */ read_lock(¤t->fs->lock); } nd->mnt = mntget(current->fs->rootmnt); @@ -1021,6 +1024,7 @@ int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata read_unlock(¤t->fs->lock); current->total_link_count = 0; retval = link_path_walk(name, nd); +out: if (unlikely(current->audit_context && nd && nd->dentry && nd->dentry->d_inode)) audit_inode(name, nd->dentry->d_inode); -- cgit v1.2.3 From 456be6cd90dbbb9b0ea01d56932d56d110d51cf7 Mon Sep 17 00:00:00 2001 From: Steve Grubb Date: Fri, 29 Apr 2005 17:30:07 +0100 Subject: [AUDIT] LOGIN message credentials Attached is a new patch that solves the issue of getting valid credentials into the LOGIN message. The current code was assuming that the audit context had already been copied. This is not always the case for LOGIN messages. To solve the problem, the patch passes the task struct to the function that emits the message where it can get valid credentials. Signed-off-by: Steve Grubb Signed-off-by: David Woodhouse --- fs/proc/base.c | 2 +- include/linux/audit.h | 2 +- kernel/auditsc.c | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 39fd336cfdb9..57554bfbed79 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -820,7 +820,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, goto out_free_page; } - length = audit_set_loginuid(task->audit_context, loginuid); + length = audit_set_loginuid(task, loginuid); if (likely(length == 0)) length = count; diff --git a/include/linux/audit.h b/include/linux/audit.h index 19f214230fec..19f04b049798 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -187,7 +187,7 @@ extern int audit_receive_filter(int type, int pid, int uid, int seq, void *data, uid_t loginuid); extern void audit_get_stamp(struct audit_context *ctx, struct timespec *t, unsigned int *serial); -extern int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid); +extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); extern uid_t audit_get_loginuid(struct audit_context *ctx); extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); #else diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 66148f81d783..37b3ac94bc47 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1010,20 +1010,21 @@ void audit_get_stamp(struct audit_context *ctx, extern int audit_set_type(struct audit_buffer *ab, int type); -int audit_set_loginuid(struct audit_context *ctx, uid_t loginuid) +int audit_set_loginuid(struct task_struct *task, uid_t loginuid) { - if (ctx) { + if (task->audit_context) { struct audit_buffer *ab; ab = audit_log_start(NULL); if (ab) { audit_log_format(ab, "login pid=%d uid=%u " "old loginuid=%u new loginuid=%u", - ctx->pid, ctx->uid, ctx->loginuid, loginuid); + task->pid, task->uid, + task->audit_context->loginuid, loginuid); audit_set_type(ab, AUDIT_LOGIN); audit_log_end(ab); } - ctx->loginuid = loginuid; + task->audit_context->loginuid = loginuid; } return 0; } -- cgit v1.2.3 From 68575476718ed1c6d6ddafeec8310b109e7a7a7f Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Apr 2005 11:10:57 -0700 Subject: [PATCH] cifs: append \* properly on ASCII servers For older servers which do not support Unicode Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/CHANGES | 4 +++- fs/cifs/cifssmb.c | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 4d2404305ab6..95483baab706 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -4,7 +4,9 @@ Fix error mapping of the TOO_MANY_LINKS (hardlinks) case. Do not oops if root user kills cifs oplock kernel thread or kills the cifsd thread (NB: killing the cifs kernel threads is not recommended, unmount and rmmod cifs will kill them when they are -no longer needed). +no longer needed). Fix readdir to ASCII servers (ie older servers +which do not support Unicode) and also require asterik. + Version 1.33 ------------ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b004fef0a42b..741ff0c69f37 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2451,12 +2451,14 @@ findFirstRetry: name_len += 2; } else { /* BB add check for overrun of SMB buf BB */ name_len = strnlen(searchName, PATH_MAX); - name_len++; /* trailing null */ /* BB fix here and in unicode clause above ie if(name_len > buffersize-header) free buffer exit; BB */ strncpy(pSMB->FileName, searchName, name_len); - pSMB->FileName[name_len] = 0; /* just in case */ + pSMB->FileName[name_len] = '\\'; + pSMB->FileName[name_len+1] = '*'; + pSMB->FileName[name_len+2] = 0; + name_len += 3; } params = 12 + name_len /* includes null */ ; -- cgit v1.2.3 From 9ea1f8f505f6f770bd593e689960ac4f893509b2 Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 30 Apr 2005 11:10:58 -0700 Subject: [PATCH] cifs: Update cifs todo list Signed-off-by: Steve French (sfrench@us.ibm.com) Signed-off-by: Linus Torvalds --- fs/cifs/TODO | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/cifs/TODO b/fs/cifs/TODO index 1e8490ed6948..8cc881694e29 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO @@ -1,4 +1,4 @@ -version 1.32 April 3, 2005 +version 1.34 April 29, 2005 A Partial List of Missing Features ================================== @@ -70,7 +70,15 @@ r) Implement O_DIRECT flag on open (already supported on mount) s) Allow remapping of last remaining character (\) to +0xF000 which (this character is valid for POSIX but not for Windows) -KNOWN BUGS (updated April 3, 2005) +t) Create UID mapping facility so server UIDs can be mapped on a per +mount or a per server basis to client UIDs or nobody if no mapping +exists. This is helpful when Unix extensions are negotiated to +allow better permission checking when UIDs differ on the server +and client. Add new protocol request to the CIFS protocol +standard for asking the server for the corresponding name of a +particular uid. + +KNOWN BUGS (updated April 29, 2005) ==================================== See http://bugzilla.samba.org - search on product "CifsVFS" for current bug list. -- cgit v1.2.3 From 552fca4cbe552520d85b21e839f289c880fa48d2 Mon Sep 17 00:00:00 2001 From: Nikita Danilov Date: Sun, 1 May 2005 08:58:39 -0700 Subject: [PATCH] mpage_writepages() page locking fix When ->writepage() returns WRITEPAGE_ACTIVATE, the page is still locked. Explicitly unlock the page in mpage_writepages(). Signed-off-by: Nikita Danilov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/mpage.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/mpage.c b/fs/mpage.c index e7d8d1a77606..3923facf94eb 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -727,6 +727,8 @@ retry: &last_block_in_bio, &ret, wbc, writepage_fn); } + if (unlikely(ret == WRITEPAGE_ACTIVATE)) + unlock_page(page); if (ret || (--(wbc->nr_to_write) <= 0)) done = 1; if (wbc->nonblocking && bdi_write_congested(bdi)) { -- cgit v1.2.3 From de7d5a3b6c9ff8429bf046c36b56d3192b75c3da Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sun, 1 May 2005 08:58:39 -0700 Subject: [PATCH] drop_buffers() oops fix In rare situations, drop_buffers() can be called for a page which has buffers, but no ->mapping (it was truncated, but the buffers were left behind because ext3 was still fiddling with them). But if there was an I/O error in a buffer_head, drop_buffers() will try to get at the address_space and will oops. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 3b12cf947aba..665db84a1f9f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2917,7 +2917,7 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free) bh = head; do { - if (buffer_write_io_error(bh)) + if (buffer_write_io_error(bh) && page->mapping) set_bit(AS_EIO, &page->mapping->flags); if (buffer_busy(bh)) goto failed; -- cgit v1.2.3 From d59dd4620fb8d6422555a9e2b82a707718e68327 Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sun, 1 May 2005 08:58:47 -0700 Subject: [PATCH] use smp_mb/wmb/rmb where possible Replace a number of memory barriers with smp_ variants. This means we won't take the unnecessary hit on UP machines. Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 6 +++--- ipc/mqueue.c | 4 ++-- kernel/kthread.c | 2 +- kernel/profile.c | 2 +- kernel/ptrace.c | 2 +- kernel/stop_machine.c | 10 +++++----- kernel/sys.c | 20 ++++++++++---------- kernel/timer.c | 2 +- lib/rwsem-spinlock.c | 6 +++--- lib/rwsem.c | 4 ++-- mm/mempool.c | 4 ++-- 11 files changed, 31 insertions(+), 31 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 665db84a1f9f..188365c79204 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -218,7 +218,7 @@ struct super_block *freeze_bdev(struct block_device *bdev) sb = get_super(bdev); if (sb && !(sb->s_flags & MS_RDONLY)) { sb->s_frozen = SB_FREEZE_WRITE; - wmb(); + smp_wmb(); sync_inodes_sb(sb, 0); DQUOT_SYNC(sb); @@ -235,7 +235,7 @@ struct super_block *freeze_bdev(struct block_device *bdev) sync_inodes_sb(sb, 1); sb->s_frozen = SB_FREEZE_TRANS; - wmb(); + smp_wmb(); sync_blockdev(sb->s_bdev); @@ -263,7 +263,7 @@ void thaw_bdev(struct block_device *bdev, struct super_block *sb) if (sb->s_op->unlockfs) sb->s_op->unlockfs(sb); sb->s_frozen = SB_UNFROZEN; - wmb(); + smp_wmb(); wake_up(&sb->s_wait_unfrozen); drop_super(sb); } diff --git a/ipc/mqueue.c b/ipc/mqueue.c index cb0cd3cf3b5a..33f71520b89c 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -767,7 +767,7 @@ static inline void pipelined_send(struct mqueue_inode_info *info, list_del(&receiver->list); receiver->state = STATE_PENDING; wake_up_process(receiver->task); - wmb(); + smp_wmb(); receiver->state = STATE_READY; } @@ -786,7 +786,7 @@ static inline void pipelined_receive(struct mqueue_inode_info *info) list_del(&sender->list); sender->state = STATE_PENDING; wake_up_process(sender->task); - wmb(); + smp_wmb(); sender->state = STATE_READY; } diff --git a/kernel/kthread.c b/kernel/kthread.c index e377e2244103..f50f174e92da 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -174,7 +174,7 @@ int kthread_stop(struct task_struct *k) /* Must init completion *before* thread sees kthread_stop_info.k */ init_completion(&kthread_stop_info.done); - wmb(); + smp_wmb(); /* Now set kthread_should_stop() to true, and wake it up. */ kthread_stop_info.k = k; diff --git a/kernel/profile.c b/kernel/profile.c index a38fa70075fe..a66be468c422 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -522,7 +522,7 @@ static int __init create_hash_tables(void) return 0; out_cleanup: prof_on = 0; - mb(); + smp_mb(); on_each_cpu(profile_nop, NULL, 0, 1); for_each_online_cpu(cpu) { struct page *page; diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 88b306c4e841..f5cc1cec0fb4 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -135,7 +135,7 @@ int ptrace_attach(struct task_struct *task) (current->gid != task->sgid) || (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) goto bad; - rmb(); + smp_rmb(); if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) goto bad; /* the same process cannot be attached many times */ diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index c39ed70af174..6116b25aa7cf 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -33,7 +33,7 @@ static int stopmachine(void *cpu) set_cpus_allowed(current, cpumask_of_cpu((int)(long)cpu)); /* Ack: we are alive */ - mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */ + smp_mb(); /* Theoretically the ack = 0 might not be on this CPU yet. */ atomic_inc(&stopmachine_thread_ack); /* Simple state machine */ @@ -43,14 +43,14 @@ static int stopmachine(void *cpu) local_irq_disable(); irqs_disabled = 1; /* Ack: irqs disabled. */ - mb(); /* Must read state first. */ + smp_mb(); /* Must read state first. */ atomic_inc(&stopmachine_thread_ack); } else if (stopmachine_state == STOPMACHINE_PREPARE && !prepared) { /* Everyone is in place, hold CPU. */ preempt_disable(); prepared = 1; - mb(); /* Must read state first. */ + smp_mb(); /* Must read state first. */ atomic_inc(&stopmachine_thread_ack); } /* Yield in first stage: migration threads need to @@ -62,7 +62,7 @@ static int stopmachine(void *cpu) } /* Ack: we are exiting. */ - mb(); /* Must read state first. */ + smp_mb(); /* Must read state first. */ atomic_inc(&stopmachine_thread_ack); if (irqs_disabled) @@ -77,7 +77,7 @@ static int stopmachine(void *cpu) static void stopmachine_set_state(enum stopmachine_state state) { atomic_set(&stopmachine_thread_ack, 0); - wmb(); + smp_wmb(); stopmachine_state = state; while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) cpu_relax(); diff --git a/kernel/sys.c b/kernel/sys.c index 462d78d55895..df2ddcc6863b 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -525,7 +525,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) if (new_egid != old_egid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } if (rgid != (gid_t) -1 || (egid != (gid_t) -1 && egid != old_rgid)) @@ -556,7 +556,7 @@ asmlinkage long sys_setgid(gid_t gid) if(old_egid != gid) { current->mm->dumpable=0; - wmb(); + smp_wmb(); } current->gid = current->egid = current->sgid = current->fsgid = gid; } @@ -565,7 +565,7 @@ asmlinkage long sys_setgid(gid_t gid) if(old_egid != gid) { current->mm->dumpable=0; - wmb(); + smp_wmb(); } current->egid = current->fsgid = gid; } @@ -596,7 +596,7 @@ static int set_user(uid_t new_ruid, int dumpclear) if(dumpclear) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->uid = new_ruid; return 0; @@ -653,7 +653,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) if (new_euid != old_euid) { current->mm->dumpable=0; - wmb(); + smp_wmb(); } current->fsuid = current->euid = new_euid; if (ruid != (uid_t) -1 || @@ -703,7 +703,7 @@ asmlinkage long sys_setuid(uid_t uid) if (old_euid != uid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->fsuid = current->euid = uid; current->suid = new_suid; @@ -748,7 +748,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) if (euid != current->euid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->euid = euid; } @@ -798,7 +798,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) if (egid != current->egid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->egid = egid; } @@ -845,7 +845,7 @@ asmlinkage long sys_setfsuid(uid_t uid) if (uid != old_fsuid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->fsuid = uid; } @@ -875,7 +875,7 @@ asmlinkage long sys_setfsgid(gid_t gid) if (gid != old_fsgid) { current->mm->dumpable = 0; - wmb(); + smp_wmb(); } current->fsgid = gid; key_fsgid_changed(current); diff --git a/kernel/timer.c b/kernel/timer.c index ecb3d67c0e14..207aa4f0aa10 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1007,7 +1007,7 @@ asmlinkage long sys_getppid(void) * Make sure we read the pid before re-reading the * parent pointer: */ - rmb(); + smp_rmb(); parent = me->group_leader->real_parent; if (old != parent) continue; diff --git a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c index 21f0db2c9711..40ffde940a86 100644 --- a/lib/rwsem-spinlock.c +++ b/lib/rwsem-spinlock.c @@ -76,7 +76,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) list_del(&waiter->list); tsk = waiter->task; /* Don't touch waiter after ->task has been NULLed */ - mb(); + smp_mb(); waiter->task = NULL; wake_up_process(tsk); put_task_struct(tsk); @@ -91,7 +91,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int wakewrite) list_del(&waiter->list); tsk = waiter->task; - mb(); + smp_mb(); waiter->task = NULL; wake_up_process(tsk); put_task_struct(tsk); @@ -123,7 +123,7 @@ __rwsem_wake_one_writer(struct rw_semaphore *sem) list_del(&waiter->list); tsk = waiter->task; - mb(); + smp_mb(); waiter->task = NULL; wake_up_process(tsk); put_task_struct(tsk); diff --git a/lib/rwsem.c b/lib/rwsem.c index 7644089ec8fa..62fa4eba9ffe 100644 --- a/lib/rwsem.c +++ b/lib/rwsem.c @@ -74,7 +74,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int downgrading) */ list_del(&waiter->list); tsk = waiter->task; - mb(); + smp_mb(); waiter->task = NULL; wake_up_process(tsk); put_task_struct(tsk); @@ -117,7 +117,7 @@ __rwsem_do_wake(struct rw_semaphore *sem, int downgrading) waiter = list_entry(next, struct rwsem_waiter, list); next = waiter->list.next; tsk = waiter->task; - mb(); + smp_mb(); waiter->task = NULL; wake_up_process(tsk); put_task_struct(tsk); diff --git a/mm/mempool.c b/mm/mempool.c index e9a0a6337b21..c9f3d4620428 100644 --- a/mm/mempool.c +++ b/mm/mempool.c @@ -229,7 +229,7 @@ repeat_alloc: /* Now start performing page reclaim */ gfp_temp = gfp_mask; prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE); - mb(); + smp_mb(); if (!pool->curr_nr) io_schedule(); finish_wait(&pool->wait, &wait); @@ -250,7 +250,7 @@ void mempool_free(void *element, mempool_t *pool) { unsigned long flags; - mb(); + smp_mb(); if (pool->curr_nr < pool->min_nr) { spin_lock_irqsave(&pool->lock, flags); if (pool->curr_nr < pool->min_nr) { -- cgit v1.2.3 From ffa0aea681a5f3c8aecbb86f1cfd3486043805de Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:58:56 -0700 Subject: [PATCH] uml - hostfs: avoid buffers Use this: .set_page_dirty = __set_page_dirty_nobuffers, We already dropped the inclusion of , and we don't have a backing block device for this FS. "Without having looked at it, I'm sure that hostfs does not use buffer_heads. So setting your ->set_page_dirty a_op to point at __set_page_dirty_nobuffers() is a reasonable thing to do - it'll provide a slight speedup." This speedup is one less spinlock held and one less conditional branch, which isn't bad. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hostfs/hostfs_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index a88ad2924851..e6c63d9cac7b 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -521,7 +521,7 @@ int hostfs_commit_write(struct file *file, struct page *page, unsigned from, static struct address_space_operations hostfs_aops = { .writepage = hostfs_writepage, .readpage = hostfs_readpage, -/* .set_page_dirty = __set_page_dirty_nobuffers, */ + .set_page_dirty = __set_page_dirty_nobuffers, .prepare_write = hostfs_prepare_write, .commit_write = hostfs_commit_write }; -- cgit v1.2.3 From cd7619d6bf36564cf54ff7218ef54e558a741913 Mon Sep 17 00:00:00 2001 From: Matt Mackall Date: Sun, 1 May 2005 08:59:01 -0700 Subject: [PATCH] Exterminate PAGE_BUG Remove PAGE_BUG - repalce it with BUG and BUG_ON. Signed-off-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm26/mm/small_page.c | 6 ++---- fs/afs/file.c | 3 +-- fs/buffer.c | 3 +-- fs/jffs2/file.c | 3 +-- fs/udf/file.c | 6 ++---- fs/udf/inode.c | 4 ++-- include/asm-cris/page.h | 4 ---- include/asm-generic/bug.h | 11 ----------- include/asm-sh64/bug.h | 4 ---- mm/filemap.c | 3 +-- 10 files changed, 10 insertions(+), 37 deletions(-) (limited to 'fs') diff --git a/arch/arm26/mm/small_page.c b/arch/arm26/mm/small_page.c index 77be86cca789..30447106c25f 100644 --- a/arch/arm26/mm/small_page.c +++ b/arch/arm26/mm/small_page.c @@ -92,8 +92,7 @@ static unsigned long __get_small_page(int priority, struct order *order) page = list_entry(order->queue.next, struct page, lru); again: #ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); + BUG_ON(USED_MAP(page) & ~order->all_used); #endif offset = ffz(USED_MAP(page)); SET_USED(page, offset); @@ -141,8 +140,7 @@ static void __free_small_page(unsigned long spage, struct order *order) goto non_small; #ifdef PEDANTIC - if (USED_MAP(page) & ~order->all_used) - PAGE_BUG(page); + BUG_ON(USED_MAP(page) & ~order->all_used); #endif spage = spage >> order->shift; diff --git a/fs/afs/file.c b/fs/afs/file.c index 6b6bb7c8abf6..23c125128024 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -131,8 +131,7 @@ static int afs_file_readpage(struct file *file, struct page *page) vnode = AFS_FS_I(inode); - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); ret = -ESTALE; if (vnode->flags & AFS_VNODE_DELETED) diff --git a/fs/buffer.c b/fs/buffer.c index 188365c79204..792cbacbbf41 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2078,8 +2078,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) int nr, i; int fully_mapped = 1; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); blocksize = 1 << inode->i_blkbits; if (!page_has_buffers(page)) create_empty_buffers(page, blocksize, 0); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 0c607c1388f4..771a554701d6 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -79,8 +79,7 @@ static int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) D2(printk(KERN_DEBUG "jffs2_do_readpage_nolock(): ino #%lu, page at offset 0x%lx\n", inode->i_ino, pg->index << PAGE_CACHE_SHIFT)); - if (!PageLocked(pg)) - PAGE_BUG(pg); + BUG_ON(!PageLocked(pg)); pg_buf = kmap(pg); /* FIXME: Can kmap fail? */ diff --git a/fs/udf/file.c b/fs/udf/file.c index 2faa4172b9f7..bb40d63f328f 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -49,8 +49,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page) struct inode *inode = page->mapping->host; char *kaddr; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); kaddr = kmap(page); memset(kaddr, 0, PAGE_CACHE_SIZE); @@ -67,8 +66,7 @@ static int udf_adinicb_writepage(struct page *page, struct writeback_control *wb struct inode *inode = page->mapping->host; char *kaddr; - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); kaddr = kmap(page); memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size); diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 0506e1173784..3d68de39fad6 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -167,8 +167,8 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) } page = grab_cache_page(inode->i_mapping, 0); - if (!PageLocked(page)) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); + if (!PageUptodate(page)) { kaddr = kmap(page); diff --git a/include/asm-cris/page.h b/include/asm-cris/page.h index ddd8915e41e6..c767da1ef8f5 100644 --- a/include/asm-cris/page.h +++ b/include/asm-cris/page.h @@ -77,10 +77,6 @@ typedef struct { unsigned long pgprot; } pgprot_t; printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ } while (0) -#define PAGE_BUG(page) do { \ - BUG(); \ -} while (0) - /* Pure 2^n version of get_order */ static inline int get_order(unsigned long size) { diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 6e5aaaa9a2fb..400c2b41896e 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -12,13 +12,6 @@ } while (0) #endif -#ifndef HAVE_ARCH_PAGE_BUG -#define PAGE_BUG(page) do { \ - printk("page BUG for page at %p\n", page); \ - BUG(); \ -} while (0) -#endif - #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0) #endif @@ -37,10 +30,6 @@ #define BUG() #endif -#ifndef HAVE_ARCH_PAGE_BUG -#define PAGE_BUG(page) do { if (page) ; } while (0) -#endif - #ifndef HAVE_ARCH_BUG_ON #define BUG_ON(condition) do { if (condition) ; } while(0) #endif diff --git a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h index 3acd54d59566..5d659ec28e10 100644 --- a/include/asm-sh64/bug.h +++ b/include/asm-sh64/bug.h @@ -17,10 +17,6 @@ BUG(); \ } while(0) -#define PAGE_BUG(page) do { \ - BUG(); \ -} while (0) - #define WARN_ON(condition) do { \ if (unlikely((condition)!=0)) { \ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \ diff --git a/mm/filemap.c b/mm/filemap.c index ee79b5d3439f..c085af2332d8 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -123,8 +123,7 @@ void remove_from_page_cache(struct page *page) { struct address_space *mapping = page->mapping; - if (unlikely(!PageLocked(page))) - PAGE_BUG(page); + BUG_ON(!PageLocked(page)); write_lock_irq(&mapping->tree_lock); __remove_from_page_cache(page); -- cgit v1.2.3 From bcf88e1163623e8e8ef2ba7feface9c826a890c9 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sun, 1 May 2005 08:59:03 -0700 Subject: [PATCH] procfs: Fix hardlink counts The pid directories in /proc/ currently return the wrong hardlink count - 3, when there are actually 4 : ".", "..", "fd", and "task". This is easy to notice using find(1): cd /proc/ find In the output, you'll see a message similar to: find: WARNING: Hard link count is wrong for .: this may be a bug in your filesystem driver. Automatically turning on find's -noleaf option. Earlier results may have failed to include directories that should have been searched. http://bugs.gentoo.org/show_bug.cgi?id=86031 I also noticed that CONFIG_SECURITY can add a 5th: attr, and performed a similar fix on the task directories too. Signed-off-by: Daniel Drake Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 39fd336cfdb9..4718173af2c8 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1800,8 +1800,12 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; inode->i_op = &proc_tgid_base_inode_operations; inode->i_fop = &proc_tgid_base_operations; - inode->i_nlink = 3; inode->i_flags|=S_IMMUTABLE; +#ifdef CONFIG_SECURITY + inode->i_nlink = 5; +#else + inode->i_nlink = 4; +#endif dentry->d_op = &pid_base_dentry_operations; @@ -1855,8 +1859,12 @@ static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; inode->i_op = &proc_tid_base_inode_operations; inode->i_fop = &proc_tid_base_operations; - inode->i_nlink = 3; inode->i_flags|=S_IMMUTABLE; +#ifdef CONFIG_SECURITY + inode->i_nlink = 4; +#else + inode->i_nlink = 3; +#endif dentry->d_op = &pid_base_dentry_operations; -- cgit v1.2.3 From f246315e1ab96c40978777d1e159820ecca45aa8 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sun, 1 May 2005 08:59:03 -0700 Subject: [PATCH] procfs: Fix hardlink counts for /proc//task The current logic assumes that a /proc//task directory should have a hardlink count of 3, probably counting ".", "..", and a directory for a single child task. It's fairly obvious that this doesn't work out correctly when a PID has more than one child task, which is quite often the case. Signed-off-by: Daniel Drake Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/proc/base.c b/fs/proc/base.c index 4718173af2c8..2eac86d46c51 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1419,6 +1419,8 @@ static struct file_operations proc_tgid_attr_operations; static struct inode_operations proc_tgid_attr_inode_operations; #endif +static int get_tid_list(int index, unsigned int *tids, struct inode *dir); + /* SMP-safe */ static struct dentry *proc_pident_lookup(struct inode *dir, struct dentry *dentry, @@ -1458,7 +1460,7 @@ static struct dentry *proc_pident_lookup(struct inode *dir, */ switch(p->type) { case PROC_TGID_TASK: - inode->i_nlink = 3; + inode->i_nlink = 2 + get_tid_list(2, NULL, dir); inode->i_op = &proc_task_inode_operations; inode->i_fop = &proc_task_operations; break; @@ -1943,7 +1945,8 @@ static int get_tid_list(int index, unsigned int *tids, struct inode *dir) if (--index >= 0) continue; - tids[nr_tids] = tid; + if (tids != NULL) + tids[nr_tids] = tid; nr_tids++; if (nr_tids >= PROC_MAXPIDS) break; @@ -2043,6 +2046,7 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi } nr_tids = get_tid_list(pos, tid_array, inode); + inode->i_nlink = pos + nr_tids; for (i = 0; i < nr_tids; i++) { unsigned long j = PROC_NUMBUF; -- cgit v1.2.3 From 9a3bb3017383fbb6fe56431d17f60bd0d50f0717 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Sun, 1 May 2005 08:59:05 -0700 Subject: [PATCH] reiserfs: make resize option auto-get new device size It's trivial for the resize option to auto-get the underlying device size, while it's harder for the user. I've copied the code from jfs. Since of the different reiserfs option parser (which does not use the superior match_token used by almost every other filesystem), I've had to use the "resize=auto" and not "resize" option to specify this behaviour. Changing the option parser to the kernel one wouldn't be bad but I've no time to do this cleanup in this moment. Btw, the mount(8) man page should be updated to include this option. Cc the relevant people, please (I hope I cc'ed the right people). Cc: Cc: Cc: Cc: Alex Zarochentsev Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/super.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index bcdf2438d152..bc5e8893b5d5 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -889,12 +889,18 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st char * p; p = NULL; - /* "resize=NNN" */ - *blocks = simple_strtoul (arg, &p, 0); - if (*p != '\0') { - /* NNN does not look like a number */ - reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); - return 0; + /* "resize=NNN" or "resize=auto" */ + + if (!strcmp(arg, "auto")) { + /* From JFS code, to auto-get the size.*/ + *blocks = s->s_bdev->bd_inode->i_size >> s->s_blocksize_bits; + } else { + *blocks = simple_strtoul (arg, &p, 0); + if (*p != '\0') { + /* NNN does not look like a number */ + reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); + return 0; + } } } @@ -903,7 +909,8 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st unsigned long val = simple_strtoul (arg, &p, 0); /* commit=NNN (time in seconds) */ if ( *p != '\0' || val >= (unsigned int)-1) { - reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); return 0; + reiserfs_warning (s, "reiserfs_parse_options: bad value %s", arg); + return 0; } *commit_max_age = (unsigned int)val; } -- cgit v1.2.3 From 127144df4ce817ad648af15a3983c8d52aacf670 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Sun, 1 May 2005 08:59:07 -0700 Subject: [PATCH] Fix rewriting on a full reiserfs filesystem Allow rewriting of a file and extending a file upto the end of the allocated block on a full filesystem. From: Chris Mason Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/file.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 26950113af8c..f6860e83521d 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -1284,10 +1284,11 @@ static ssize_t reiserfs_file_write( struct file *file, /* the file we are going reiserfs_claim_blocks_to_be_allocated(inode->i_sb, num_pages << (PAGE_CACHE_SHIFT - inode->i_blkbits)); reiserfs_write_unlock(inode->i_sb); - if ( !num_pages ) { /* If we do not have enough space even for */ - res = -ENOSPC; /* single page, return -ENOSPC */ - if ( pos > (inode->i_size & (inode->i_sb->s_blocksize-1))) - break; // In case we are writing past the file end, break. + if ( !num_pages ) { /* If we do not have enough space even for a single page... */ + if ( pos > inode->i_size+inode->i_sb->s_blocksize-(pos & (inode->i_sb->s_blocksize-1))) { + res = -ENOSPC; + break; // In case we are writing past the end of the last file block, break. + } // Otherwise we are possibly overwriting the file, so // let's set write size to be equal or less than blocksize. // This way we get it correctly for file holes. -- cgit v1.2.3 From 74f9f974a64dc3de554aa1977bf108334436e47b Mon Sep 17 00:00:00 2001 From: Edward Shishkin Date: Sun, 1 May 2005 08:59:09 -0700 Subject: [PATCH] reiserfs: journal_init fix This fixes segmentation fault when specifying bad journal device via a mount option. Don't pass a zero pointer to bdevname() if filp_open() returns error. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index c9ad3a7849f4..b16d65acb550 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2306,13 +2306,16 @@ static int journal_init_dev( struct super_block *super, if( !IS_ERR( journal -> j_dev_file ) ) { struct inode *jdev_inode = journal->j_dev_file->f_mapping->host; if( !S_ISBLK( jdev_inode -> i_mode ) ) { - reiserfs_warning (super, "journal_init_dev: '%s' is " - "not a block device", jdev_name ); + reiserfs_warning(super, "journal_init_dev: '%s' is " + "not a block device", jdev_name ); result = -ENOTBLK; + release_journal_dev( super, journal ); } else { /* ok */ journal->j_dev_bd = I_BDEV(jdev_inode); set_blocksize(journal->j_dev_bd, super->s_blocksize); + reiserfs_info(super, "journal_init_dev: journal device: %s\n", + bdevname(journal->j_dev_bd, b)); } } else { result = PTR_ERR( journal -> j_dev_file ); @@ -2321,11 +2324,6 @@ static int journal_init_dev( struct super_block *super, "journal_init_dev: Cannot open '%s': %i", jdev_name, result ); } - if( result != 0 ) { - release_journal_dev( super, journal ); - } - reiserfs_info(super, "journal_init_dev: journal device: %s\n", - bdevname(journal->j_dev_bd, b)); return result; } -- cgit v1.2.3 From 7ed20e1ad521b5f5df61bf6559ae60738e393741 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 1 May 2005 08:59:14 -0700 Subject: [PATCH] convert that currently tests _NSIG directly to use valid_signal() Convert most of the current code that uses _NSIG directly to instead use valid_signal(). This avoids gcc -W warnings and off-by-one errors. Signed-off-by: Jesper Juhl Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/ptrace.c | 5 +++-- arch/arm/kernel/ptrace.c | 5 +++-- arch/arm26/kernel/ptrace.c | 5 +++-- arch/cris/arch-v10/kernel/ptrace.c | 5 +++-- arch/frv/kernel/ptrace.c | 5 +++-- arch/h8300/kernel/ptrace.c | 5 +++-- arch/i386/kernel/ptrace.c | 5 +++-- arch/ia64/kernel/ptrace.c | 5 +++-- arch/m32r/kernel/ptrace.c | 5 +++-- arch/m68k/kernel/ptrace.c | 5 +++-- arch/m68knommu/kernel/ptrace.c | 5 +++-- arch/mips/kernel/ptrace.c | 3 ++- arch/mips/kernel/ptrace32.c | 3 ++- arch/parisc/kernel/ptrace.c | 7 ++++--- arch/ppc/kernel/ptrace.c | 5 +++-- arch/ppc64/kernel/ptrace.c | 5 +++-- arch/ppc64/kernel/ptrace32.c | 5 +++-- arch/s390/kernel/ptrace.c | 5 +++-- arch/sh/kernel/ptrace.c | 5 +++-- arch/sh64/kernel/ptrace.c | 5 +++-- arch/sparc/kernel/ptrace.c | 3 ++- arch/sparc64/kernel/ptrace.c | 3 ++- arch/um/kernel/ptrace.c | 4 ++-- arch/v850/kernel/ptrace.c | 3 ++- arch/x86_64/kernel/ptrace.c | 5 +++-- drivers/char/vt_ioctl.c | 3 ++- fs/fcntl.c | 3 ++- ipc/mqueue.c | 4 ++-- kernel/exit.c | 5 +++-- kernel/futex.c | 3 ++- kernel/ptrace.c | 3 ++- kernel/signal.c | 9 +++++---- kernel/sys.c | 3 ++- 33 files changed, 90 insertions(+), 59 deletions(-) (limited to 'fs') diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c index d00583161574..bbd37536d14e 100644 --- a/arch/alpha/kernel/ptrace.c +++ b/arch/alpha/kernel/ptrace.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -335,7 +336,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -365,7 +366,7 @@ do_sys_ptrace(long request, long pid, long addr, long data, case PTRACE_SINGLESTEP: /* execute single instruction. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; /* Mark single stepping. */ child->thread_info->bpt_nsaved = -1; diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index efd7a341614b..cd99b83f14c2 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -693,7 +694,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat case PTRACE_SYSCALL: case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -728,7 +729,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat */ case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->ptrace |= PT_SINGLESTEP; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index 2a137146a77c..8a52124de0e1 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -591,7 +592,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat case PTRACE_SYSCALL: case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -626,7 +627,7 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat */ case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->ptrace |= PT_SINGLESTEP; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index da15db8ae482..581ecabaae53 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -184,7 +185,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { @@ -219,7 +220,7 @@ sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index 2a0efb739adc..cbe03cba9f02 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -239,7 +240,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -267,7 +268,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); ptrace_enable(child); diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index 5f19d774a288..05c15e869777 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -171,7 +172,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data >= _NSIG) + if (!valid_signal(data)) break ; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -202,7 +203,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index b2f17640ceff..e8c965ce86eb 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -511,7 +512,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -543,7 +544,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_singlestep(child); diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 55789fcd7210..c253fd5914fc 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -1481,7 +1482,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if (data > _NSIG) + if (!valid_signal(data)) goto out_tsk; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -1520,7 +1521,7 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data) /* let child execute for one instruction */ case PTRACE_SINGLEBLOCK: ret = -EIO; - if (data > _NSIG) + if (!valid_signal(data)) goto out_tsk; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c index 8b40f362dd6f..124f7c1b775e 100644 --- a/arch/m32r/kernel/ptrace.c +++ b/arch/m32r/kernel/ptrace.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -665,7 +666,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) case PTRACE_SYSCALL: case PTRACE_CONT: ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -700,7 +701,7 @@ do_ptrace(long request, struct task_struct *child, long addr, long data) unsigned long pc, insn; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); if ((child->ptrace & PT_DTRACE) == 0) { diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index 0beb53333ba3..f4e1e5eb8e12 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -251,7 +252,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { child->thread.work.syscall_trace = ~0; @@ -292,7 +293,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->thread.work.syscall_trace = 0; tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 15cf79080b15..9724e1cd82e5 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -240,7 +241,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -278,7 +279,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 92f2c39afe27..a2f899c2f4d4 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -257,7 +258,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index 611dee919d50..eee207969c21 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -241,7 +242,7 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned int) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 2937a9236384..c07db9dff7cd 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -285,7 +286,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) ret = -EIO; DBG("sys_ptrace(%s)\n", request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"); - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) goto out_tsk; child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); if (request == PTRACE_SYSCALL) { @@ -311,7 +312,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) case PTRACE_SINGLEBLOCK: DBG("sys_ptrace(SINGLEBLOCK)\n"); ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) goto out_tsk; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->ptrace &= ~PT_SINGLESTEP; @@ -328,7 +329,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data) case PTRACE_SINGLESTEP: DBG("sys_ptrace(SINGLESTEP)\n"); ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) goto out_tsk; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c index 426b6f7d9de3..59d59a8dc249 100644 --- a/arch/ppc/kernel/ptrace.c +++ b/arch/ppc/kernel/ptrace.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -356,7 +357,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -389,7 +390,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_single_step(child); diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c index 354a287c67eb..5a846324ca8c 100644 --- a/arch/ppc64/kernel/ptrace.c +++ b/arch/ppc64/kernel/ptrace.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -162,7 +163,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -194,7 +195,7 @@ int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_single_step(child); diff --git a/arch/ppc64/kernel/ptrace32.c b/arch/ppc64/kernel/ptrace32.c index ee81b1b776cc..16436426c7e2 100644 --- a/arch/ppc64/kernel/ptrace32.c +++ b/arch/ppc64/kernel/ptrace32.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -293,7 +294,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -325,7 +326,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); set_single_step(child); diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 647233c02fc8..9f0d73e3f5f7 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -609,7 +610,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) /* continue and stop at next (return from) syscall */ case PTRACE_CONT: /* restart after signal. */ - if ((unsigned long) data >= _NSIG) + if (!valid_signal(data)) return -EIO; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -637,7 +638,7 @@ do_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_SINGLESTEP: /* set the trap flag. */ - if ((unsigned long) data >= _NSIG) + if (!valid_signal(data)) return -EIO; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->exit_code = data; diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1b0dfb4d8ea4..b28919b65682 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -197,7 +198,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -228,7 +229,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) struct pt_regs *dummy = NULL; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); if ((child->ptrace & PT_DTRACE) == 0) { diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 800288c1562b..fd2000956dae 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -255,7 +256,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); @@ -285,7 +286,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) struct pt_regs *regs; ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); if ((child->ptrace & PT_DTRACE) == 0) { diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index c4f93bd2daf2..475c4c13462c 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -526,7 +527,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) addr = 1; case PTRACE_CONT: { /* restart after signal. */ - if (data > _NSIG) { + if (!valid_signal(data)) { pt_error_return(regs, EIO); goto out_tsk; } diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 5f080cf04b33..80a76e2ad732 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -559,7 +560,7 @@ asmlinkage void do_ptrace(struct pt_regs *regs) addr = 1; case PTRACE_CONT: { /* restart after signal. */ - if (data > _NSIG) { + if (!valid_signal(data)) { pt_error_return(regs, EIO); goto out_tsk; } diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 3a99ee6d94eb..e50e60ff5d27 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -143,7 +143,7 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; child->ptrace &= ~PT_DTRACE; @@ -179,7 +179,7 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_SINGLESTEP: { /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); child->ptrace |= PT_DTRACE; diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index 8fa780757dcd..4726b87f5e5a 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -208,7 +209,7 @@ int sys_ptrace(long request, long pid, long addr, long data) /* Execute a single instruction. */ case PTRACE_SINGLESTEP: rval = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; /* Turn CHILD's single-step flag on or off. */ diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index c7011675007d..c64b9c97c745 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -467,7 +468,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data case PTRACE_CONT: /* restart after signal. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; if (request == PTRACE_SYSCALL) set_tsk_thread_flag(child,TIF_SYSCALL_TRACE); @@ -529,7 +530,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data case PTRACE_SINGLESTEP: /* set the trap flag. */ ret = -EIO; - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) break; clear_tsk_thread_flag(child,TIF_SYSCALL_TRACE); set_singlestep(child); diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 5d386f4bea49..8971484b956b 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -641,7 +642,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, extern int spawnpid, spawnsig; if (!perm || !capable(CAP_KILL)) return -EPERM; - if (arg < 1 || arg > _NSIG || arg == SIGKILL) + if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) return -EINVAL; spawnpid = current->pid; spawnsig = arg; diff --git a/fs/fcntl.c b/fs/fcntl.c index 3e7ab16ed154..286a9f8f3d49 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -308,7 +309,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, break; case F_SETSIG: /* arg == 0 restores default behaviour. */ - if (arg < 0 || arg > _NSIG) { + if (!valid_signal(arg)) { break; } err = 0; diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 33f71520b89c..0acf245f441d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "util.h" @@ -976,8 +977,7 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, notification.sigev_notify != SIGEV_THREAD)) return -EINVAL; if (notification.sigev_notify == SIGEV_SIGNAL && - (notification.sigev_signo < 0 || - notification.sigev_signo > _NSIG)) { + !valid_signal(notification.sigev_signo)) { return -EINVAL; } if (notification.sigev_notify == SIGEV_THREAD) { diff --git a/kernel/exit.c b/kernel/exit.c index 93851bcd9584..eb8da36e13df 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -277,7 +278,7 @@ void set_special_pids(pid_t session, pid_t pgrp) */ int allow_signal(int sig) { - if (sig < 1 || sig > _NSIG) + if (!valid_signal(sig) || sig < 1) return -EINVAL; spin_lock_irq(¤t->sighand->siglock); @@ -298,7 +299,7 @@ EXPORT_SYMBOL(allow_signal); int disallow_signal(int sig) { - if (sig < 1 || sig > _NSIG) + if (!valid_signal(sig) || sig < 1) return -EINVAL; spin_lock_irq(¤t->sighand->siglock); diff --git a/kernel/futex.c b/kernel/futex.c index 7b54a672d0ad..c7130f86106c 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -39,6 +39,7 @@ #include #include #include +#include #define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8) @@ -654,7 +655,7 @@ static int futex_fd(unsigned long uaddr, int signal) int ret, err; ret = -EINVAL; - if (signal < 0 || signal > _NSIG) + if (!valid_signal(signal)) goto out; ret = get_unused_fd(); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index f5cc1cec0fb4..8dcb8f6288bc 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -166,7 +167,7 @@ bad: int ptrace_detach(struct task_struct *child, unsigned int data) { - if ((unsigned long) data > _NSIG) + if (!valid_signal(data)) return -EIO; /* Architecture-specific hardware disable .. */ diff --git a/kernel/signal.c b/kernel/signal.c index e6567d7f2b62..8f3debc77c5b 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -646,7 +647,7 @@ static int check_kill_permission(int sig, struct siginfo *info, struct task_struct *t) { int error = -EINVAL; - if (sig < 0 || sig > _NSIG) + if (!valid_signal(sig)) return error; error = -EPERM; if ((!info || ((unsigned long)info != 1 && @@ -1245,7 +1246,7 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) * Make sure legacy kernel users don't send in bad values * (normal paths check this in check_kill_permission). */ - if (sig < 0 || sig > _NSIG) + if (!valid_signal(sig)) return -EINVAL; /* @@ -1520,7 +1521,7 @@ void do_notify_parent(struct task_struct *tsk, int sig) if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) sig = 0; } - if (sig > 0 && sig <= _NSIG) + if (valid_signal(sig) && sig > 0) __group_send_sig_info(sig, &info, tsk->parent); __wake_up_parent(tsk, tsk->parent); spin_unlock_irqrestore(&psig->siglock, flags); @@ -2364,7 +2365,7 @@ do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact) { struct k_sigaction *k; - if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig))) + if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig))) return -EINVAL; k = ¤t->sighand->action[sig-1]; diff --git a/kernel/sys.c b/kernel/sys.c index 7f43d6e62c7a..f64e97cabe25 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1637,7 +1638,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, switch (option) { case PR_SET_PDEATHSIG: sig = arg2; - if (sig < 0 || sig > _NSIG) { + if (!valid_signal(sig)) { error = -EINVAL; break; } -- cgit v1.2.3 From 212079cf4ee99e492a57b817e796825d423a30bb Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Sun, 1 May 2005 08:59:15 -0700 Subject: [PATCH] aio: remove superfluous kiocb member initialization This patch removes superfluous kiocb member initialization in the AIO allocation and deallocation path. For example, in really_put_req(), right before kiocb is returned to slab, 5 variables are reset to NULL. The same variables will be initialized at the kiocb allocation time, so why bother reset them knowing that they will be set to valid data at alloc time? Another example: ki_retry is initialized in __aio_get_req, but is initialized again in io_submit_one. Signed-off-by: Ken Chen Cc: Benjamin LaHaise Cc: Suparna Bhattacharya Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index a82214d2e46d..9f807a541fbe 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -405,7 +405,6 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx) req->ki_ctx = ctx; req->ki_cancel = NULL; req->ki_retry = NULL; - req->ki_obj.user = NULL; req->ki_dtor = NULL; req->private = NULL; INIT_LIST_HEAD(&req->ki_run_list); @@ -451,11 +450,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req) { if (req->ki_dtor) req->ki_dtor(req); - req->ki_ctx = NULL; - req->ki_filp = NULL; - req->ki_obj.user = NULL; - req->ki_dtor = NULL; - req->private = NULL; kmem_cache_free(kiocb_cachep, req); ctx->reqs_active--; @@ -1515,8 +1509,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, } req->ki_filp = file; - iocb->aio_key = req->ki_key; - ret = put_user(iocb->aio_key, &user_iocb->aio_key); + ret = put_user(req->ki_key, &user_iocb->aio_key); if (unlikely(ret)) { dprintk("EFAULT: aio_key\n"); goto out_put_req; @@ -1531,8 +1524,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, req->ki_opcode = iocb->aio_lio_opcode; init_waitqueue_func_entry(&req->ki_wait, aio_wake_function); INIT_LIST_HEAD(&req->ki_wait.task_list); - req->ki_run_list.next = req->ki_run_list.prev = NULL; - req->ki_retry = NULL; req->ki_retried = 0; req->ki_kicked = 0; req->ki_queued = 0; -- cgit v1.2.3 From 4bf69b2a06090c01c27f25ea5cd1440f7bf9256f Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Sun, 1 May 2005 08:59:15 -0700 Subject: [PATCH] aio: ring wrapping simplification Since the tail pointer in aio_ring structure never wrap ring size more than once, so a simple compare is sufficient to wrap the index around. This avoid a more expensive mod operation. Signed-off-by: Ken Chen Cc: Benjamin LaHaise Cc: Suparna Bhattacharya Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 9f807a541fbe..40517f35daae 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -978,7 +978,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) tail = info->tail; event = aio_ring_event(info, tail, KM_IRQ0); - tail = (tail + 1) % info->nr; + if (++tail >= info->nr) + tail = 0; event->obj = (u64)(unsigned long)iocb->ki_obj.user; event->data = iocb->ki_user_data; -- cgit v1.2.3 From 644d3a088a3b862ed0b57c286cf58a6bd338ce08 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Sun, 1 May 2005 08:59:15 -0700 Subject: [PATCH] aio: clean up debug code Clean up code that was previously used for debug purpose. Remove aio_run, aio_wakeups, iocb->ki_queued and iocb->ki_kicked. Also clean up unused variable count in __aio_run_iocbs() and debug code in read_events(). Signed-off-by: Ken Chen Cc: Benjamin LaHaise Cc: Suparna Bhattacharya Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 40517f35daae..674bb47fed29 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -40,9 +40,6 @@ #define dprintk(x...) do { ; } while (0) #endif -static long aio_run = 0; /* for testing only */ -static long aio_wakeups = 0; /* for testing only */ - /*------ sysctl variables----*/ atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ @@ -617,7 +614,6 @@ static inline int __queue_kicked_iocb(struct kiocb *iocb) if (list_empty(&iocb->ki_run_list)) { list_add_tail(&iocb->ki_run_list, &ctx->run_list); - iocb->ki_queued++; return 1; } return 0; @@ -658,10 +654,8 @@ static ssize_t aio_run_iocb(struct kiocb *iocb) } if (!(iocb->ki_retried & 0xff)) { - pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n", - iocb->ki_retried, - iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes, - iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups); + pr_debug("%ld retry: %d of %d\n", iocb->ki_retried, + iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes); } if (!(retry = iocb->ki_retry)) { @@ -768,7 +762,6 @@ out: static int __aio_run_iocbs(struct kioctx *ctx) { struct kiocb *iocb; - int count = 0; LIST_HEAD(run_list); list_splice_init(&ctx->run_list, &run_list); @@ -783,9 +776,7 @@ static int __aio_run_iocbs(struct kioctx *ctx) aio_run_iocb(iocb); if (__aio_put_req(ctx, iocb)) /* drop extra ref */ put_ioctx(ctx); - count++; } - aio_run++; if (!list_empty(&ctx->run_list)) return 1; return 0; @@ -884,10 +875,8 @@ static void queue_kicked_iocb(struct kiocb *iocb) spin_lock_irqsave(&ctx->ctx_lock, flags); run = __queue_kicked_iocb(iocb); spin_unlock_irqrestore(&ctx->ctx_lock, flags); - if (run) { + if (run) aio_queue_work(ctx); - aio_wakeups++; - } } /* @@ -907,7 +896,6 @@ void fastcall kick_iocb(struct kiocb *iocb) return; } - iocb->ki_kicked++; /* If its already kicked we shouldn't queue it again */ if (!kiocbTryKick(iocb)) { queue_kicked_iocb(iocb); @@ -1003,10 +991,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2) pr_debug("added to ring %p at [%lu]\n", iocb, tail); - pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n", - iocb->ki_retried, - iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes, - iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups); + pr_debug("%ld retries: %d of %d\n", iocb->ki_retried, + iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes); put_rq: /* everything turned out well, dispose of the aiocb. */ ret = __aio_put_req(ctx, iocb); @@ -1114,7 +1100,6 @@ static int read_events(struct kioctx *ctx, int i = 0; struct io_event ent; struct aio_timeout to; - int event_loop = 0; /* testing only */ int retry = 0; /* needed to zero any padding within an entry (there shouldn't be @@ -1181,7 +1166,6 @@ retry: if (to.timed_out) /* Only check after read evt */ break; schedule(); - event_loop++; if (signal_pending(tsk)) { ret = -EINTR; break; @@ -1209,9 +1193,6 @@ retry: if (timeout) clear_timeout(&to); out: - pr_debug("event loop executed %d times\n", event_loop); - pr_debug("aio_run %ld\n", aio_run); - pr_debug("aio_wakeups %ld\n", aio_wakeups); return i ? i : ret; } @@ -1526,10 +1507,6 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, init_waitqueue_func_entry(&req->ki_wait, aio_wake_function); INIT_LIST_HEAD(&req->ki_wait.task_list); req->ki_retried = 0; - req->ki_kicked = 0; - req->ki_queued = 0; - aio_run = 0; - aio_wakeups = 0; ret = aio_setup_iocb(req); -- cgit v1.2.3 From 954d3e95369cf73b4bc1e570729f68264a0e6fe0 Mon Sep 17 00:00:00 2001 From: Ken Chen Date: Sun, 1 May 2005 08:59:16 -0700 Subject: [PATCH] aio: optimize io_submit_one() This patch optimizes io_submit_one to call aio_run_iocb() directly if ctx->run_list is empty. When the list is empty, the operation of adding to the list, then call to __aio_run_iocbs() is unnecessary because these operations are done in one atomic step. ctx->run_list always has only one element in this case. This optimization speeds up industry standard db transaction processing benchmark by 0.2%. Signed-off-by: Ken Chen Cc: Benjamin LaHaise Cc: Suparna Bhattacharya Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/aio.c b/fs/aio.c index 674bb47fed29..7afa222f6802 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1514,10 +1514,14 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, goto out_put_req; spin_lock_irq(&ctx->ctx_lock); - list_add_tail(&req->ki_run_list, &ctx->run_list); - /* drain the run list */ - while (__aio_run_iocbs(ctx)) - ; + if (likely(list_empty(&ctx->run_list))) { + aio_run_iocb(req); + } else { + list_add_tail(&req->ki_run_list, &ctx->run_list); + /* drain the run list */ + while (__aio_run_iocbs(ctx)) + ; + } spin_unlock_irq(&ctx->ctx_lock); aio_put_req(req); /* drop extra ref to req */ return 0; -- cgit v1.2.3 From 945b092011c6af71a0107be96e119c8c08776f3f Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Sun, 1 May 2005 08:59:16 -0700 Subject: [PATCH] hfs, hfsplus: don't leak s_fs_info and fix an oops This patch fixes the leak of sb->s_fs_info in both the HFS and HFS+ modules. In addition to this, it fixes an oops happening when trying to mount a non-hfsplus filesystem using hfsplus. This patch is from Roman Zippel, based off patches sent by myself. Signed-off-by: Colin Leroy Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfs/mdb.c | 5 +++++ fs/hfs/super.c | 8 +++----- fs/hfsplus/super.c | 6 +++++- 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c index 4efb640c4d0c..217e32f37e0b 100644 --- a/fs/hfs/mdb.c +++ b/fs/hfs/mdb.c @@ -333,6 +333,8 @@ void hfs_mdb_close(struct super_block *sb) * Release the resources associated with the in-core MDB. */ void hfs_mdb_put(struct super_block *sb) { + if (!HFS_SB(sb)) + return; /* free the B-trees */ hfs_btree_close(HFS_SB(sb)->ext_tree); hfs_btree_close(HFS_SB(sb)->cat_tree); @@ -340,4 +342,7 @@ void hfs_mdb_put(struct super_block *sb) /* free the buffers holding the primary and alternate MDBs */ brelse(HFS_SB(sb)->mdb_bh); brelse(HFS_SB(sb)->alt_mdb_bh); + + kfree(HFS_SB(sb)); + sb->s_fs_info = NULL; } diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 1e2c193134cc..ab783f6afa3b 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -297,7 +297,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) res = -EINVAL; if (!parse_options((char *)data, sbi)) { hfs_warn("hfs_fs: unable to parse mount options.\n"); - goto bail3; + goto bail; } sb->s_op = &hfs_super_operations; @@ -310,7 +310,7 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent) hfs_warn("VFS: Can't find a HFS filesystem on dev %s.\n", hfs_mdb_name(sb)); res = -EINVAL; - goto bail2; + goto bail; } /* try to get the root inode */ @@ -340,10 +340,8 @@ bail_iput: iput(root_inode); bail_no_root: hfs_warn("hfs_fs: get root inode failed.\n"); +bail: hfs_mdb_put(sb); -bail2: -bail3: - kfree(sbi); return res; } diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 5f8044664a3c..d55ad67b8e42 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -208,7 +208,9 @@ static void hfsplus_write_super(struct super_block *sb) static void hfsplus_put_super(struct super_block *sb) { dprint(DBG_SUPER, "hfsplus_put_super\n"); - if (!(sb->s_flags & MS_RDONLY)) { + if (!sb->s_fs_info) + return; + if (!(sb->s_flags & MS_RDONLY) && HFSPLUS_SB(sb).s_vhdr) { struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; vhdr->modify_date = hfsp_now2mt(); @@ -226,6 +228,8 @@ static void hfsplus_put_super(struct super_block *sb) brelse(HFSPLUS_SB(sb).s_vhbh); if (HFSPLUS_SB(sb).nls) unload_nls(HFSPLUS_SB(sb).nls); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; } static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) -- cgit v1.2.3 From 4dcd00b18118d174c4b8d838c11f437f0af3c20c Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Sun, 1 May 2005 08:59:16 -0700 Subject: [PATCH] autofs4: wait order fix It's possible for an event wait request to arive before the event requestor. If this happens the daemon never gets notified and autofs hangs. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/autofs_i.h | 1 + fs/autofs4/waitq.c | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'fs') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index f5a52c871726..978987735252 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -84,6 +84,7 @@ struct autofs_wait_queue { char *name; /* This is for status reporting upon return */ int status; + atomic_t notified; atomic_t wait_ctr; }; diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c index 1ab24a662e09..5a40d36e5a51 100644 --- a/fs/autofs4/waitq.c +++ b/fs/autofs4/waitq.c @@ -210,17 +210,8 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, wq->len = len; wq->status = -EINTR; /* Status return if interrupted */ atomic_set(&wq->wait_ctr, 2); + atomic_set(&wq->notified, 1); up(&sbi->wq_sem); - - DPRINTK("new wait id = 0x%08lx, name = %.*s, nfy=%d", - (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); - /* autofs4_notify_daemon() may block */ - if (notify != NFY_NONE) { - autofs4_notify_daemon(sbi,wq, - notify == NFY_MOUNT ? - autofs_ptype_missing : - autofs_ptype_expire_multi); - } } else { atomic_inc(&wq->wait_ctr); up(&sbi->wq_sem); @@ -229,6 +220,17 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry, (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify); } + if (notify != NFY_NONE && atomic_dec_and_test(&wq->notified)) { + int type = (notify == NFY_MOUNT ? + autofs_ptype_missing : autofs_ptype_expire_multi); + + DPRINTK(("new wait id = 0x%08lx, name = %.*s, nfy=%d\n", + (unsigned long) wq->wait_queue_token, wq->len, wq->name, notify)); + + /* autofs4_notify_daemon() may block */ + autofs4_notify_daemon(sbi, wq, type); + } + /* wq->name is NULL if and only if the lock is already released */ if ( sbi->catatonic ) { -- cgit v1.2.3 From 3a9720ce73c9247e5262922d65e90444ea75eb50 Mon Sep 17 00:00:00 2001 From: Ian Kent Date: Sun, 1 May 2005 08:59:17 -0700 Subject: [PATCH] autofs4: tree race fix For tree mount maps, a call to chdir or chroot, to a directory above the moint point directories at a certain time during the expire results in the expire incorrectly thinking the tree is not busy. This patch adds a check to see if the filesystem above the tree mount points is busy and also locks the filesystem during the tree mount expire to prevent the race. Signed-off-by: Ian Kent Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/autofs4/autofs_i.h | 14 ++++++++++++-- fs/autofs4/expire.c | 16 ++++++++++++++-- fs/autofs4/inode.c | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h index 978987735252..c7b2b8890188 100644 --- a/fs/autofs4/autofs_i.h +++ b/fs/autofs4/autofs_i.h @@ -102,6 +102,7 @@ struct autofs_sb_info { int needs_reghost; struct super_block *sb; struct semaphore wq_sem; + spinlock_t fs_lock; struct autofs_wait_queue *queues; /* Wait queue pointer */ }; @@ -127,9 +128,18 @@ static inline int autofs4_oz_mode(struct autofs_sb_info *sbi) { static inline int autofs4_ispending(struct dentry *dentry) { struct autofs_info *inf = autofs4_dentry_ino(dentry); + int pending = 0; - return (dentry->d_flags & DCACHE_AUTOFS_PENDING) || - (inf != NULL && inf->flags & AUTOFS_INF_EXPIRING); + if (dentry->d_flags & DCACHE_AUTOFS_PENDING) + return 1; + + if (inf) { + spin_lock(&inf->sbi->fs_lock); + pending = inf->flags & AUTOFS_INF_EXPIRING; + spin_unlock(&inf->sbi->fs_lock); + } + + return pending; } static inline void autofs4_copy_atime(struct file *src, struct file *dst) diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 31540a6404d9..500425e24fba 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -99,6 +99,10 @@ static int autofs4_check_tree(struct vfsmount *mnt, if (!autofs4_can_expire(top, timeout, do_now)) return 0; + /* Is someone visiting anywhere in the tree ? */ + if (may_umount_tree(mnt)) + return 0; + spin_lock(&dcache_lock); repeat: next = this_parent->d_subdirs.next; @@ -270,10 +274,18 @@ static struct dentry *autofs4_expire(struct super_block *sb, /* Case 2: tree mount, expire iff entire tree is not busy */ if (!exp_leaves) { + /* Lock the tree as we must expire as a whole */ + spin_lock(&sbi->fs_lock); if (autofs4_check_tree(mnt, dentry, timeout, do_now)) { - expired = dentry; - break; + struct autofs_info *inf = autofs4_dentry_ino(dentry); + + /* Set this flag early to catch sys_chdir and the like */ + inf->flags |= AUTOFS_INF_EXPIRING; + spin_unlock(&sbi->fs_lock); + expired = dentry; + break; } + spin_unlock(&sbi->fs_lock); /* Case 3: direct mount, expire individual leaves */ } else { expired = autofs4_check_leaves(mnt, dentry, timeout, do_now); diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c index a52560746628..4bb14cc68040 100644 --- a/fs/autofs4/inode.c +++ b/fs/autofs4/inode.c @@ -206,6 +206,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent) sbi->version = 0; sbi->sub_version = 0; init_MUTEX(&sbi->wq_sem); + spin_lock_init(&sbi->fs_lock); sbi->queues = NULL; s->s_blocksize = 1024; s->s_blocksize_bits = 10; -- cgit v1.2.3 From 6a3a16f2ef6f335286e2b2bf8284b0ab4ff38ec0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:17 -0700 Subject: [PATCH] reiserfs endianness: clone struct reiserfs_key struct reiserfs_key cloned; (currently) identical struct in_core_key added. Places that expect host-endian data in reiserfs_key switched to in_core_key. Basically, we get annotation of reiserfs_key users and keep the resulting tree obviously equivalent to original. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/bitmap.c | 4 ++-- fs/reiserfs/stree.c | 1 + fs/reiserfs/super.c | 4 ++-- include/linux/reiserfs_fs.h | 32 +++++++++++++++++++++++++++++--- 4 files changed, 34 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index a4e2ed544bbe..f4f16fada14c 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -736,7 +736,7 @@ static inline int this_blocknr_allocation_would_make_it_a_large_file(reiserfs_bl #ifdef DISPLACE_NEW_PACKING_LOCALITIES static inline void displace_new_packing_locality (reiserfs_blocknr_hint_t *hint) { - struct reiserfs_key * key = &hint->key; + struct in_core_key * key = &hint->key; hint->th->displace_new_blocks = 0; hint->search_start = hint->beg + keyed_hash((char*)(&key->k_objectid),4) % (hint->end - hint->beg); @@ -777,7 +777,7 @@ static inline int old_way (reiserfs_blocknr_hint_t * hint) static inline void hundredth_slices (reiserfs_blocknr_hint_t * hint) { - struct reiserfs_key * key = &hint->key; + struct in_core_key * key = &hint->key; b_blocknr_t slice_start; slice_start = (keyed_hash((char*)(&key->k_dir_id),4) % 100) * (hint->end / 100); diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 73ec5212178b..1d380a5da39c 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -229,6 +229,7 @@ const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; /* Maximal possible key. It is never in the tree. */ const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index bc5e8893b5d5..d6d1d7e2801f 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -110,7 +110,7 @@ static void reiserfs_unlockfs(struct super_block *s) { reiserfs_allow_writes(s) ; } -extern const struct reiserfs_key MAX_KEY; +extern const struct in_core_key MAX_IN_CORE_KEY; /* this is used to delete "save link" when there are no items of a @@ -164,7 +164,7 @@ static int finish_unfinished (struct super_block * s) /* compose key to look for "save" links */ max_cpu_key.version = KEY_FORMAT_3_5; - max_cpu_key.on_disk_key = MAX_KEY; + max_cpu_key.on_disk_key = MAX_IN_CORE_KEY; max_cpu_key.key_length = 3; #ifdef CONFIG_QUOTA diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index bccff8b17dc4..d0867873a1b5 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -433,6 +433,23 @@ static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ) # define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val)) #endif +struct in_core_offset_v1 { + __u32 k_offset; + __u32 k_uniqueness; +} __attribute__ ((__packed__)); + +struct in_core_offset_v2 { +#ifdef __LITTLE_ENDIAN + /* little endian version */ + __u64 k_offset:60; + __u64 k_type: 4; +#else + /* big endian version */ + __u64 k_type: 4; + __u64 k_offset:60; +#endif +} __attribute__ ((__packed__)); + /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { @@ -445,9 +462,18 @@ struct reiserfs_key { } __attribute__ ((__packed__)) u; } __attribute__ ((__packed__)); +struct in_core_key { + __u32 k_dir_id; /* packing locality: by default parent + directory object id */ + __u32 k_objectid; /* object identifier */ + union { + struct in_core_offset_v1 k_offset_v1; + struct in_core_offset_v2 k_offset_v2; + } __attribute__ ((__packed__)) u; +} __attribute__ ((__packed__)); struct cpu_key { - struct reiserfs_key on_disk_key; + struct in_core_key on_disk_key; int version; int key_length; /* 3 in all cases but direct2indirect and indirect2direct conversion */ @@ -1476,7 +1502,7 @@ struct tree_balance int fs_gen; /* saved value of `reiserfs_generation' counter see FILESYSTEM_CHANGED() macro in reiserfs_fs.h */ #ifdef DISPLACE_NEW_PACKING_LOCALITIES - struct reiserfs_key key; /* key pointer, to pass to block allocator or + struct in_core_key key; /* key pointer, to pass to block allocator or another low-level subsystem */ #endif } ; @@ -2117,7 +2143,7 @@ struct buffer_head * get_FEB (struct tree_balance *); struct __reiserfs_blocknr_hint { struct inode * inode; /* inode passed to allocator, if we allocate unf. nodes */ long block; /* file offset, in blocks */ - struct reiserfs_key key; + struct in_core_key key; struct path * path; /* search path, used by allocator to deternine search_start by * various ways */ struct reiserfs_transaction_handle * th; /* transaction handle is needed to log super blocks and -- cgit v1.2.3 From 3e8962be915bacc1d70e4849a075041838d60a3f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:18 -0700 Subject: [PATCH] reiserfs endianness: annotate little-endian objects little-endian objects annotated as such; again, obviously no changes of resulting code, we only replace __u16 with __le16, etc. in relevant places. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/bitmap.c | 7 +- fs/reiserfs/dir.c | 8 +- fs/reiserfs/file.c | 4 +- fs/reiserfs/inode.c | 10 +-- fs/reiserfs/item_ops.c | 5 +- fs/reiserfs/objectid.c | 18 ++--- fs/reiserfs/procfs.c | 4 +- fs/reiserfs/stree.c | 22 ++++-- fs/reiserfs/super.c | 6 +- include/linux/reiserfs_acl.h | 12 +-- include/linux/reiserfs_fs.h | 168 ++++++++++++++++++++--------------------- include/linux/reiserfs_xattr.h | 4 +- 12 files changed, 138 insertions(+), 130 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index f4f16fada14c..49c479c9454a 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -260,8 +260,9 @@ static inline int block_group_used(struct super_block *s, u32 id) { /* * the packing is returned in disk byte order */ -u32 reiserfs_choose_packing(struct inode *dir) { - u32 packing; +__le32 reiserfs_choose_packing(struct inode *dir) +{ + __le32 packing; if (TEST_OPTION(packing_groups, dir->i_sb)) { u32 parent_dir = le32_to_cpu(INODE_PKEY(dir)->k_dir_id); /* @@ -655,7 +656,7 @@ static int get_left_neighbor(reiserfs_blocknr_hint_t *hint) struct buffer_head * bh; struct item_head * ih; int pos_in_item; - __u32 * item; + __le32 * item; int ret = 0; if (!hint->path) /* reiserfs code can call this function w/o pointer to path diff --git a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c index d1514a9b0514..fbde4b01a325 100644 --- a/fs/reiserfs/dir.c +++ b/fs/reiserfs/dir.c @@ -209,8 +209,8 @@ static int reiserfs_readdir (struct file * filp, void * dirent, filldir_t filldi /* compose directory item containing "." and ".." entries (entries are not aligned to 4 byte boundary) */ /* the last four params are LE */ -void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid) +void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid) { struct reiserfs_de_head * deh; @@ -242,8 +242,8 @@ void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, } /* compose directory item containing "." and ".." entries */ -void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid) +void make_empty_dir_item (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid) { struct reiserfs_de_head * deh; diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index f6860e83521d..2230afff1870 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c @@ -166,7 +166,7 @@ static int reiserfs_allocate_blocks_for_region( struct cpu_key key; // cpu key of item that we are going to deal with struct item_head *ih; // pointer to item head that we are going to deal with struct buffer_head *bh; // Buffer head that contains items that we are going to deal with - __u32 * item; // pointer to item we are going to deal with + __le32 * item; // pointer to item we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. b_blocknr_t *allocated_blocks; // Pointer to a place where allocated blocknumbers would be stored. reiserfs_blocknr_hint_t hint; // hint structure for block allocator. @@ -891,7 +891,7 @@ static int reiserfs_prepare_file_region_for_write( struct item_head *ih = NULL; // pointer to item head that we are going to deal with struct buffer_head *itembuf=NULL; // Buffer head that contains items that we are going to deal with INITIALIZE_PATH(path); // path to item, that we are going to deal with. - __u32 * item=NULL; // pointer to item we are going to deal with + __le32 * item=NULL; // pointer to item we are going to deal with int item_pos=-1; /* Position in indirect item */ diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 7543031396f4..5fdb9f97b99e 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -173,7 +173,7 @@ static inline void fix_tail_page_for_writing(struct page *page) { done already or non-hole position has been found in the indirect item */ static inline int allocation_needed (int retval, b_blocknr_t allocated, struct item_head * ih, - __u32 * item, int pos_in_item) + __le32 * item, int pos_in_item) { if (allocated) return 0; @@ -278,7 +278,7 @@ research: bh = get_last_bh (&path); ih = get_ih (&path); if (is_indirect_le_ih (ih)) { - __u32 * ind_item = (__u32 *)B_I_PITEM (bh, ih); + __le32 * ind_item = (__le32 *)B_I_PITEM (bh, ih); /* FIXME: here we could cache indirect item or part of it in the inode to avoid search_by_key in case of subsequent @@ -581,7 +581,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block, struct cpu_key key; struct buffer_head * bh, * unbh = NULL; struct item_head * ih, tmp_ih; - __u32 * item; + __le32 * item; int done; int fs_gen; struct reiserfs_transaction_handle *th = NULL; @@ -746,7 +746,7 @@ start_trans: done = 0; do { if (is_statdata_le_ih (ih)) { - __u32 unp = 0; + __le32 unp = 0; struct cpu_key tmp_key; /* indirect item has to be inserted */ @@ -2067,7 +2067,7 @@ static int map_block_for_writepage(struct inode *inode, struct item_head tmp_ih ; struct item_head *ih ; struct buffer_head *bh ; - __u32 *item ; + __le32 *item ; struct cpu_key key ; INITIALIZE_PATH(path) ; int pos_in_item ; diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c index 9cf7c13b120d..0ce33db1acdf 100644 --- a/fs/reiserfs/item_ops.c +++ b/fs/reiserfs/item_ops.c @@ -296,10 +296,11 @@ static void print_sequence (__u32 start, int len) static void indirect_print_item (struct item_head * ih, char * item) { int j; - __u32 * unp, prev = INT_MAX; + __le32 * unp; + __u32 prev = INT_MAX; int num; - unp = (__u32 *)item; + unp = (__le32 *)item; if (ih_item_len(ih) % UNFM_P_SIZE) reiserfs_warning (NULL, "indirect_print_item: invalid item len"); diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c index 0785c43a7486..bfe8e25ef293 100644 --- a/fs/reiserfs/objectid.c +++ b/fs/reiserfs/objectid.c @@ -11,13 +11,13 @@ // find where objectid map starts #define objectid_map(s,rs) (old_format_only (s) ? \ - (__u32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ - (__u32 *)((rs) + 1)) + (__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\ + (__le32 *)((rs) + 1)) #ifdef CONFIG_REISERFS_CHECK -static void check_objectid_map (struct super_block * s, __u32 * map) +static void check_objectid_map (struct super_block * s, __le32 * map) { if (le32_to_cpu (map[0]) != 1) reiserfs_panic (s, "vs-15010: check_objectid_map: map corrupted: %lx", @@ -27,7 +27,7 @@ static void check_objectid_map (struct super_block * s, __u32 * map) } #else -static void check_objectid_map (struct super_block * s, __u32 * map) +static void check_objectid_map (struct super_block * s, __le32 * map) {;} #endif @@ -52,7 +52,7 @@ __u32 reiserfs_get_unused_objectid (struct reiserfs_transaction_handle *th) { struct super_block * s = th->t_super; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); - __u32 * map = objectid_map (s, rs); + __le32 * map = objectid_map (s, rs); __u32 unused_objectid; BUG_ON (!th->t_trans_id); @@ -97,7 +97,7 @@ void reiserfs_release_objectid (struct reiserfs_transaction_handle *th, { struct super_block * s = th->t_super; struct reiserfs_super_block * rs = SB_DISK_SUPER_BLOCK (s); - __u32 * map = objectid_map (s, rs); + __le32 * map = objectid_map (s, rs); int i = 0; BUG_ON (!th->t_trans_id); @@ -172,12 +172,12 @@ int reiserfs_convert_objectid_map_v1(struct super_block *s) { int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2 ; int old_max = sb_oid_maxsize(disk_sb); struct reiserfs_super_block_v1 *disk_sb_v1 ; - __u32 *objectid_map, *new_objectid_map ; + __le32 *objectid_map, *new_objectid_map ; int i ; disk_sb_v1=(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data); - objectid_map = (__u32 *)(disk_sb_v1 + 1) ; - new_objectid_map = (__u32 *)(disk_sb + 1) ; + objectid_map = (__le32 *)(disk_sb_v1 + 1) ; + new_objectid_map = (__le32 *)(disk_sb + 1) ; if (cur_size > new_size) { /* mark everyone used that was listed as free at the end of the objectid diff --git a/fs/reiserfs/procfs.c b/fs/reiserfs/procfs.c index f4ea81ae0e0f..e242ebc7f6f6 100644 --- a/fs/reiserfs/procfs.c +++ b/fs/reiserfs/procfs.c @@ -73,8 +73,8 @@ int reiserfs_global_version_in_proc( char *buffer, char **start, off_t offset, #define DFL( x ) D4C( rs -> s_v1.x ) #define objectid_map( s, rs ) (old_format_only (s) ? \ - (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ - (__u32 *)(rs + 1)) + (__le32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \ + (__le32 *)(rs + 1)) #define MAP( i ) D4C( objectid_map( sb, rs )[ i ] ) #define DJF( x ) le32_to_cpu( rs -> x ) diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 1d380a5da39c..15fa4cbdce3e 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -87,10 +87,11 @@ inline void copy_item_head(struct item_head * p_v_to, inline int comp_short_keys (const struct reiserfs_key * le_key, const struct cpu_key * cpu_key) { - __u32 * p_s_le_u32, * p_s_cpu_u32; + __le32 * p_s_le_u32; + __u32 * p_s_cpu_u32; int n_key_length = REISERFS_SHORT_KEY_LEN; - p_s_le_u32 = (__u32 *)le_key; + p_s_le_u32 = (__le32 *)le_key; p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key; for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) { if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 ) @@ -228,7 +229,12 @@ extern struct tree_balance * cur_tb; const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}}; /* Maximal possible key. It is never in the tree. */ -const struct reiserfs_key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct reiserfs_key MAX_KEY = { + __constant_cpu_to_le32(0xffffffff), + __constant_cpu_to_le32(0xffffffff), + {{__constant_cpu_to_le32(0xffffffff), + __constant_cpu_to_le32(0xffffffff)},} +}; const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; @@ -998,7 +1004,7 @@ static char prepare_for_delete_or_cut( int n_unfm_number, /* Number of the item unformatted nodes. */ n_counter, n_blk_size; - __u32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */ + __le32 * p_n_unfm_pointer; /* Pointer to the unformatted node number. */ __u32 tmp; struct item_head s_ih; /* Item header. */ char c_mode; /* Returned mode of the balance. */ @@ -1060,7 +1066,7 @@ static char prepare_for_delete_or_cut( /* pointers to be cut */ n_unfm_number -= pos_in_item (p_s_path); /* Set pointer to the last unformatted node pointer that is to be cut. */ - p_n_unfm_pointer = (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed; + p_n_unfm_pointer = (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1 - *p_n_removed; /* We go through the unformatted nodes pointers of the indirect @@ -1082,8 +1088,8 @@ static char prepare_for_delete_or_cut( need_research = 1 ; break; } - RFALSE( p_n_unfm_pointer < (__u32 *)B_I_PITEM(p_s_bh, &s_ih) || - p_n_unfm_pointer > (__u32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1, + RFALSE( p_n_unfm_pointer < (__le32 *)B_I_PITEM(p_s_bh, &s_ih) || + p_n_unfm_pointer > (__le32 *)B_I_PITEM(p_s_bh, &s_ih) + I_UNFM_NUM(&s_ih) - 1, "vs-5265: pointer out of range"); /* Hole, nothing to remove. */ @@ -1432,7 +1438,7 @@ int reiserfs_delete_object (struct reiserfs_transaction_handle *th, struct inode #if defined( USE_INODE_GENERATION_COUNTER ) if( !old_format_only ( th -> t_super ) ) { - __u32 *inode_generation; + __le32 *inode_generation; inode_generation = &REISERFS_SB(th -> t_super) -> s_rs -> s_inode_generation; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index d6d1d7e2801f..2283f18aa1dc 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -216,7 +216,7 @@ static int finish_unfinished (struct super_block * s) /* reiserfs_iget needs k_dirid and k_objectid only */ item = B_I_PITEM (bh, ih); - obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__u32 *)item); + obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item); obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; @@ -304,7 +304,7 @@ void add_save_link (struct reiserfs_transaction_handle * th, int retval; struct cpu_key key; struct item_head ih; - __u32 link; + __le32 link; BUG_ON (!th->t_trans_id); @@ -1336,7 +1336,7 @@ static int read_super_block (struct super_block * s, int offset) return 1; } - if ( rs->s_v1.s_root_block == -1 ) { + if ( rs->s_v1.s_root_block == cpu_to_le32(-1) ) { brelse(bh) ; reiserfs_warning (s, "Unfinished reiserfsck --rebuild-tree run detected. Please run\n" "reiserfsck --rebuild-tree and wait for a completion. If that fails\n" diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h index a57e973af0bd..2aef9c3f5ce8 100644 --- a/include/linux/reiserfs_acl.h +++ b/include/linux/reiserfs_acl.h @@ -5,18 +5,18 @@ #define REISERFS_ACL_VERSION 0x0001 typedef struct { - __u16 e_tag; - __u16 e_perm; - __u32 e_id; + __le16 e_tag; + __le16 e_perm; + __le32 e_id; } reiserfs_acl_entry; typedef struct { - __u16 e_tag; - __u16 e_perm; + __le16 e_tag; + __le16 e_perm; } reiserfs_acl_entry_short; typedef struct { - __u32 a_version; + __le32 a_version; } reiserfs_acl_header; static inline size_t reiserfs_acl_size(int count) diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index d0867873a1b5..cc39c5305b80 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -114,47 +114,47 @@ if( !( cond ) ) \ struct journal_params { - __u32 jp_journal_1st_block; /* where does journal start from on its + __le32 jp_journal_1st_block; /* where does journal start from on its * device */ - __u32 jp_journal_dev; /* journal device st_rdev */ - __u32 jp_journal_size; /* size of the journal */ - __u32 jp_journal_trans_max; /* max number of blocks in a transaction. */ - __u32 jp_journal_magic; /* random value made on fs creation (this + __le32 jp_journal_dev; /* journal device st_rdev */ + __le32 jp_journal_size; /* size of the journal */ + __le32 jp_journal_trans_max; /* max number of blocks in a transaction. */ + __le32 jp_journal_magic; /* random value made on fs creation (this * was sb_journal_block_count) */ - __u32 jp_journal_max_batch; /* max number of blocks to batch into a + __le32 jp_journal_max_batch; /* max number of blocks to batch into a * trans */ - __u32 jp_journal_max_commit_age; /* in seconds, how old can an async + __le32 jp_journal_max_commit_age; /* in seconds, how old can an async * commit be */ - __u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction + __le32 jp_journal_max_trans_age; /* in seconds, how old can a transaction * be */ }; /* this is the super from 3.5.X, where X >= 10 */ struct reiserfs_super_block_v1 { - __u32 s_block_count; /* blocks count */ - __u32 s_free_blocks; /* free blocks count */ - __u32 s_root_block; /* root block number */ + __le32 s_block_count; /* blocks count */ + __le32 s_free_blocks; /* free blocks count */ + __le32 s_root_block; /* root block number */ struct journal_params s_journal; - __u16 s_blocksize; /* block size */ - __u16 s_oid_maxsize; /* max size of object id array, see + __le16 s_blocksize; /* block size */ + __le16 s_oid_maxsize; /* max size of object id array, see * get_objectid() commentary */ - __u16 s_oid_cursize; /* current size of object id array */ - __u16 s_umount_state; /* this is set to 1 when filesystem was + __le16 s_oid_cursize; /* current size of object id array */ + __le16 s_umount_state; /* this is set to 1 when filesystem was * umounted, to 2 - when not */ char s_magic[10]; /* reiserfs magic string indicates that * file system is reiserfs: * "ReIsErFs" or "ReIsEr2Fs" or "ReIsEr3Fs" */ - __u16 s_fs_state; /* it is set to used by fsck to mark which + __le16 s_fs_state; /* it is set to used by fsck to mark which * phase of rebuilding is done */ - __u32 s_hash_function_code; /* indicate, what hash function is being use + __le32 s_hash_function_code; /* indicate, what hash function is being use * to sort names in a directory*/ - __u16 s_tree_height; /* height of disk tree */ - __u16 s_bmap_nr; /* amount of bitmap blocks needed to address + __le16 s_tree_height; /* height of disk tree */ + __le16 s_bmap_nr; /* amount of bitmap blocks needed to address * each block of file system */ - __u16 s_version; /* this field is only reliable on filesystem + __le16 s_version; /* this field is only reliable on filesystem * with non-standard journal */ - __u16 s_reserved_for_journal; /* size in blocks of journal area on main + __le16 s_reserved_for_journal; /* size in blocks of journal area on main * device, we need to keep after * making fs with non-standard journal */ } __attribute__ ((__packed__)); @@ -165,8 +165,8 @@ struct reiserfs_super_block_v1 struct reiserfs_super_block { struct reiserfs_super_block_v1 s_v1; - __u32 s_inode_generation; - __u32 s_flags; /* Right now used only by inode-attributes, if enabled */ + __le32 s_inode_generation; + __le32 s_flags; /* Right now used only by inode-attributes, if enabled */ unsigned char s_uuid[16]; /* filesystem unique identifier */ unsigned char s_label[16]; /* filesystem volume label */ char s_unused[88] ; /* zero filled by mkreiserfs and @@ -269,7 +269,7 @@ int is_reiserfs_jr (struct reiserfs_super_block * rs); #define QUOTA_EXCEEDED -6 typedef __u32 b_blocknr_t; -typedef __u32 unp_t; +typedef __le32 unp_t; struct unfm_nodeinfo { unp_t unfm_nodenum; @@ -376,8 +376,8 @@ static inline struct reiserfs_sb_info *REISERFS_SB(const struct super_block *sb) // directories use this key as well as old files // struct offset_v1 { - __u32 k_offset; - __u32 k_uniqueness; + __le32 k_offset; + __le32 k_uniqueness; } __attribute__ ((__packed__)); struct offset_v2 { @@ -453,9 +453,9 @@ struct in_core_offset_v2 { /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { - __u32 k_dir_id; /* packing locality: by default parent + __le32 k_dir_id; /* packing locality: by default parent directory object id */ - __u32 k_objectid; /* object identifier */ + __le32 k_objectid; /* object identifier */ union { struct offset_v1 k_offset_v1; struct offset_v2 k_offset_v2; @@ -534,15 +534,15 @@ struct item_head item. Note that the key, not this field, is used to determine the item type, and thus which field this union contains. */ - __u16 ih_free_space_reserved; + __le16 ih_free_space_reserved; /* Iff this is a directory item, this field equals the number of directory entries in the directory item. */ - __u16 ih_entry_count; + __le16 ih_entry_count; } __attribute__ ((__packed__)) u; - __u16 ih_item_len; /* total size of the item body */ - __u16 ih_item_location; /* an offset to the item body + __le16 ih_item_len; /* total size of the item body */ + __le16 ih_item_location; /* an offset to the item body * within the block */ - __u16 ih_version; /* 0 for all old items, 2 for new + __le16 ih_version; /* 0 for all old items, 2 for new ones. Highest bit is set by fsck temporary, cleaned after all done */ @@ -778,10 +778,10 @@ extern struct reiserfs_key root_key; /* Header of a disk block. More precisely, header of a formatted leaf or internal node, and not the header of an unformatted node. */ struct block_head { - __u16 blk_level; /* Level of a block in the tree. */ - __u16 blk_nr_item; /* Number of keys/items in a block. */ - __u16 blk_free_space; /* Block free space in bytes. */ - __u16 blk_reserved; + __le16 blk_level; /* Level of a block in the tree. */ + __le16 blk_nr_item; /* Number of keys/items in a block. */ + __le16 blk_free_space; /* Block free space in bytes. */ + __le16 blk_reserved; /* dump this in v4/planA */ struct reiserfs_key blk_right_delim_key; /* kept only for compatibility */ }; @@ -845,19 +845,19 @@ struct block_head { // struct stat_data_v1 { - __u16 sd_mode; /* file type, permissions */ - __u16 sd_nlink; /* number of hard links */ - __u16 sd_uid; /* owner */ - __u16 sd_gid; /* group */ - __u32 sd_size; /* file size */ - __u32 sd_atime; /* time of last access */ - __u32 sd_mtime; /* time file was last modified */ - __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ + __le16 sd_mode; /* file type, permissions */ + __le16 sd_nlink; /* number of hard links */ + __le16 sd_uid; /* owner */ + __le16 sd_gid; /* group */ + __le32 sd_size; /* file size */ + __le32 sd_atime; /* time of last access */ + __le32 sd_mtime; /* time file was last modified */ + __le32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ union { - __u32 sd_rdev; - __u32 sd_blocks; /* number of blocks file uses */ + __le32 sd_rdev; + __le32 sd_blocks; /* number of blocks file uses */ } __attribute__ ((__packed__)) u; - __u32 sd_first_direct_byte; /* first byte of file which is stored + __le32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals ~(__u32)0 there is no @@ -923,20 +923,20 @@ struct stat_data_v1 /* Stat Data on disk (reiserfs version of UFS disk inode minus the address blocks) */ struct stat_data { - __u16 sd_mode; /* file type, permissions */ - __u16 sd_attrs; /* persistent inode flags */ - __u32 sd_nlink; /* number of hard links */ - __u64 sd_size; /* file size */ - __u32 sd_uid; /* owner */ - __u32 sd_gid; /* group */ - __u32 sd_atime; /* time of last access */ - __u32 sd_mtime; /* time file was last modified */ - __u32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ - __u32 sd_blocks; + __le16 sd_mode; /* file type, permissions */ + __le16 sd_attrs; /* persistent inode flags */ + __le32 sd_nlink; /* number of hard links */ + __le64 sd_size; /* file size */ + __le32 sd_uid; /* owner */ + __le32 sd_gid; /* group */ + __le32 sd_atime; /* time of last access */ + __le32 sd_mtime; /* time file was last modified */ + __le32 sd_ctime; /* time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ + __le32 sd_blocks; union { - __u32 sd_rdev; - __u32 sd_generation; - //__u32 sd_first_direct_byte; + __le32 sd_rdev; + __le32 sd_generation; + //__le32 sd_first_direct_byte; /* first byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals @@ -1019,12 +1019,12 @@ struct stat_data { struct reiserfs_de_head { - __u32 deh_offset; /* third component of the directory entry key */ - __u32 deh_dir_id; /* objectid of the parent directory of the object, that is referenced + __le32 deh_offset; /* third component of the directory entry key */ + __le32 deh_dir_id; /* objectid of the parent directory of the object, that is referenced by directory entry */ - __u32 deh_objectid; /* objectid of the object, that is referenced by directory entry */ - __u16 deh_location; /* offset of name in the whole item */ - __u16 deh_state; /* whether 1) entry contains stat data (for future), and 2) whether + __le32 deh_objectid; /* objectid of the object, that is referenced by directory entry */ + __le16 deh_location; /* offset of name in the whole item */ + __le16 deh_state; /* whether 1) entry contains stat data (for future), and 2) whether entry is hidden (unlinked) */ } __attribute__ ((__packed__)); #define DEH_SIZE sizeof(struct reiserfs_de_head) @@ -1084,10 +1084,10 @@ struct reiserfs_de_head #define de_visible(deh) test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define de_hidden(deh) !test_bit_unaligned (DEH_Visible, &((deh)->deh_state)) -extern void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid); -extern void make_empty_dir_item (char * body, __u32 dirid, __u32 objid, - __u32 par_dirid, __u32 par_objid); +extern void make_empty_dir_item_v1 (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid); +extern void make_empty_dir_item (char * body, __le32 dirid, __le32 objid, + __le32 par_dirid, __le32 par_objid); /* array of the entry headers */ /* get item body */ @@ -1186,9 +1186,9 @@ struct reiserfs_dir_entry /* Disk child pointer: The pointer from an internal node of the tree to a node that is on disk. */ struct disk_child { - __u32 dc_block_number; /* Disk child's block number. */ - __u16 dc_size; /* Disk child's used space. */ - __u16 dc_reserved; + __le32 dc_block_number; /* Disk child's block number. */ + __le16 dc_size; /* Disk child's used space. */ + __le16 dc_reserved; }; #define DC_SIZE (sizeof(struct disk_child)) @@ -1656,10 +1656,10 @@ struct reiserfs_iget_args { /* first block written in a commit. */ struct reiserfs_journal_desc { - __u32 j_trans_id ; /* id of commit */ - __u32 j_len ; /* length of commit. len +1 is the commit block */ - __u32 j_mount_id ; /* mount id of this trans*/ - __u32 j_realblock[1] ; /* real locations for each block */ + __le32 j_trans_id ; /* id of commit */ + __le32 j_len ; /* length of commit. len +1 is the commit block */ + __le32 j_mount_id ; /* mount id of this trans*/ + __le32 j_realblock[1] ; /* real locations for each block */ } ; #define get_desc_trans_id(d) le32_to_cpu((d)->j_trans_id) @@ -1672,9 +1672,9 @@ struct reiserfs_journal_desc { /* last block written in a commit */ struct reiserfs_journal_commit { - __u32 j_trans_id ; /* must match j_trans_id from the desc block */ - __u32 j_len ; /* ditto */ - __u32 j_realblock[1] ; /* real locations for each block */ + __le32 j_trans_id ; /* must match j_trans_id from the desc block */ + __le32 j_len ; /* ditto */ + __le32 j_realblock[1] ; /* real locations for each block */ } ; #define get_commit_trans_id(c) le32_to_cpu((c)->j_trans_id) @@ -1689,9 +1689,9 @@ struct reiserfs_journal_commit { ** and this transaction does not need to be replayed. */ struct reiserfs_journal_header { - __u32 j_last_flush_trans_id ; /* id of last fully flushed transaction */ - __u32 j_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */ - __u32 j_mount_id ; + __le32 j_last_flush_trans_id ; /* id of last fully flushed transaction */ + __le32 j_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */ + __le32 j_mount_id ; /* 12 */ struct journal_params jh_journal; } ; @@ -2170,7 +2170,7 @@ void reiserfs_init_alloc_options (struct super_block *s); * to use for a new object underneat it. The locality is returned * in disk byte order (le). */ -u32 reiserfs_choose_packing(struct inode *dir); +__le32 reiserfs_choose_packing(struct inode *dir); int is_reusable (struct super_block * s, b_blocknr_t block, int bit_value); void reiserfs_free_block (struct reiserfs_transaction_handle *th, struct inode *, b_blocknr_t, int for_unformatted); diff --git a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h index 1eaa48eca811..9244c5748820 100644 --- a/include/linux/reiserfs_xattr.h +++ b/include/linux/reiserfs_xattr.h @@ -10,8 +10,8 @@ #define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */ struct reiserfs_xattr_header { - __u32 h_magic; /* magic number for identification */ - __u32 h_hash; /* hash of the value */ + __le32 h_magic; /* magic number for identification */ + __le32 h_hash; /* hash of the value */ }; #ifdef __KERNEL__ -- cgit v1.2.3 From b8cc936f6295bba23513a49d858ea82f64982faf Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:18 -0700 Subject: [PATCH] reiserfs endianness: fix endianness bugs fixes for a couple of bugs exposed by the above: le32_to_cpu() used on 16bit value and missing conversion in comparison of host- and little-endian values. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/journal.c | 2 +- include/linux/reiserfs_fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index b16d65acb550..3072cfdee959 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2391,7 +2391,7 @@ int journal_init(struct super_block *p_s_sb, const char * j_dev_name, int old_fo jh = (struct reiserfs_journal_header *)(bhjh->b_data); /* make sure that journal matches to the super block */ - if (is_reiserfs_jr(rs) && (jh->jh_journal.jp_journal_magic != sb_jp_journal_magic(rs))) { + if (is_reiserfs_jr(rs) && (le32_to_cpu(jh->jh_journal.jp_journal_magic) != sb_jp_journal_magic(rs))) { reiserfs_warning (p_s_sb, "sh-460: journal header magic %x " "(device %s) does not match to magic found in super " "block %x", diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index cc39c5305b80..2f7a34d636dd 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -225,7 +225,7 @@ struct reiserfs_super_block #define SB_ONDISK_JOURNAL_DEVICE(s) \ le32_to_cpu ((SB_ONDISK_JP(s)->jp_journal_dev)) #define SB_ONDISK_RESERVED_FOR_JOURNAL(s) \ - le32_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal)) + le16_to_cpu ((SB_V1_DISK_SUPER_BLOCK(s)->s_reserved_for_journal)) #define is_block_in_log_or_reserved_area(s, block) \ block >= SB_JOURNAL_1st_RESERVED_BLOCK(s) \ -- cgit v1.2.3 From 6b9f5829e6e3af44f20c681e26524c637d4f82ff Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 1 May 2005 08:59:19 -0700 Subject: [PATCH] reiserfs endianness: comp_short_keys() cleanup comp_short_keys() massaged into sane form, which kills the last place where pointer to in_core_key (or any object containing such) would be cast to or from something else. At that point we are free to change layout of in_core_key - nothing depends on it anymore. So we drop the mess with union in there and simply use (unconditional) __u64 k_offset and __u8 k_type instead; places using in_core_key switched to those. That gives _far_ better code than current mess - on all platforms. Signed-off-by: Al Viro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/inode.c | 4 ++-- fs/reiserfs/stree.c | 36 ++++++++++++++------------------- fs/reiserfs/super.c | 4 ++-- include/linux/reiserfs_fs.h | 49 ++++++++------------------------------------- 4 files changed, 27 insertions(+), 66 deletions(-) (limited to 'fs') diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 5fdb9f97b99e..2711dff1b7b4 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1341,8 +1341,8 @@ void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args key.version = KEY_FORMAT_3_5; key.on_disk_key.k_dir_id = dirino; key.on_disk_key.k_objectid = inode->i_ino; - key.on_disk_key.u.k_offset_v1.k_offset = SD_OFFSET; - key.on_disk_key.u.k_offset_v1.k_uniqueness = SD_UNIQUENESS; + key.on_disk_key.k_offset = 0; + key.on_disk_key.k_type = 0; /* look for the object's stat data */ retval = search_item (inode->i_sb, &key, &path_to_sd); diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 15fa4cbdce3e..da23ba75f3d5 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -87,23 +87,20 @@ inline void copy_item_head(struct item_head * p_v_to, inline int comp_short_keys (const struct reiserfs_key * le_key, const struct cpu_key * cpu_key) { - __le32 * p_s_le_u32; - __u32 * p_s_cpu_u32; - int n_key_length = REISERFS_SHORT_KEY_LEN; - - p_s_le_u32 = (__le32 *)le_key; - p_s_cpu_u32 = (__u32 *)&cpu_key->on_disk_key; - for( ; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32 ) { - if ( le32_to_cpu (*p_s_le_u32) < *p_s_cpu_u32 ) + __u32 n; + n = le32_to_cpu(le_key->k_dir_id); + if (n < cpu_key->on_disk_key.k_dir_id) return -1; - if ( le32_to_cpu (*p_s_le_u32) > *p_s_cpu_u32 ) + if (n > cpu_key->on_disk_key.k_dir_id) + return 1; + n = le32_to_cpu(le_key->k_objectid); + if (n < cpu_key->on_disk_key.k_objectid) + return -1; + if (n > cpu_key->on_disk_key.k_objectid) return 1; - } - return 0; } - /* k1 is pointer to on-disk structure which is stored in little-endian form. k2 is pointer to cpu variable. Compare keys using all 4 key fields. @@ -153,18 +150,15 @@ inline int comp_short_le_keys (const struct reiserfs_key * key1, const struct re inline void le_key2cpu_key (struct cpu_key * to, const struct reiserfs_key * from) { + int version; to->on_disk_key.k_dir_id = le32_to_cpu (from->k_dir_id); to->on_disk_key.k_objectid = le32_to_cpu (from->k_objectid); // find out version of the key - to->version = le_key_version (from); - if (to->version == KEY_FORMAT_3_5) { - to->on_disk_key.u.k_offset_v1.k_offset = le32_to_cpu (from->u.k_offset_v1.k_offset); - to->on_disk_key.u.k_offset_v1.k_uniqueness = le32_to_cpu (from->u.k_offset_v1.k_uniqueness); - } else { - to->on_disk_key.u.k_offset_v2.k_offset = offset_v2_k_offset(&from->u.k_offset_v2); - to->on_disk_key.u.k_offset_v2.k_type = offset_v2_k_type(&from->u.k_offset_v2); - } + version = le_key_version (from); + to->version = version; + to->on_disk_key.k_offset = le_key_k_offset(version, from); + to->on_disk_key.k_type = le_key_k_type(version, from); } @@ -235,8 +229,8 @@ const struct reiserfs_key MAX_KEY = { {{__constant_cpu_to_le32(0xffffffff), __constant_cpu_to_le32(0xffffffff)},} }; -const struct in_core_key MAX_IN_CORE_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}}; +const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15}; /* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom of the path, and going upwards. We must check the path's validity at each step. If the key is not in diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 2283f18aa1dc..31e75125f48b 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -218,8 +218,8 @@ static int finish_unfinished (struct super_block * s) item = B_I_PITEM (bh, ih); obj_key.on_disk_key.k_dir_id = le32_to_cpu (*(__le32 *)item); obj_key.on_disk_key.k_objectid = le32_to_cpu (ih->ih_key.k_objectid); - obj_key.on_disk_key.u.k_offset_v1.k_offset = 0; - obj_key.on_disk_key.u.k_offset_v1.k_uniqueness = 0; + obj_key.on_disk_key.k_offset = 0; + obj_key.on_disk_key.k_type = 0; pathrelse (&path); diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h index 2f7a34d636dd..d445b682ce00 100644 --- a/include/linux/reiserfs_fs.h +++ b/include/linux/reiserfs_fs.h @@ -433,23 +433,6 @@ static inline void set_offset_v2_k_offset( struct offset_v2 *v2, loff_t offset ) # define set_offset_v2_k_offset(v2,val) (offset_v2_k_offset(v2) = (val)) #endif -struct in_core_offset_v1 { - __u32 k_offset; - __u32 k_uniqueness; -} __attribute__ ((__packed__)); - -struct in_core_offset_v2 { -#ifdef __LITTLE_ENDIAN - /* little endian version */ - __u64 k_offset:60; - __u64 k_type: 4; -#else - /* big endian version */ - __u64 k_type: 4; - __u64 k_offset:60; -#endif -} __attribute__ ((__packed__)); - /* Key of an item determines its location in the S+tree, and is composed of 4 components */ struct reiserfs_key { @@ -466,11 +449,9 @@ struct in_core_key { __u32 k_dir_id; /* packing locality: by default parent directory object id */ __u32 k_objectid; /* object identifier */ - union { - struct in_core_offset_v1 k_offset_v1; - struct in_core_offset_v2 k_offset_v2; - } __attribute__ ((__packed__)) u; -} __attribute__ ((__packed__)); + __u64 k_offset; + __u8 k_type; +}; struct cpu_key { struct in_core_key on_disk_key; @@ -696,43 +677,29 @@ static inline void set_le_ih_k_type (struct item_head * ih, int type) // static inline loff_t cpu_key_k_offset (const struct cpu_key * key) { - return (key->version == KEY_FORMAT_3_5) ? - key->on_disk_key.u.k_offset_v1.k_offset : - key->on_disk_key.u.k_offset_v2.k_offset; + return key->on_disk_key.k_offset; } static inline loff_t cpu_key_k_type (const struct cpu_key * key) { - return (key->version == KEY_FORMAT_3_5) ? - uniqueness2type (key->on_disk_key.u.k_offset_v1.k_uniqueness) : - key->on_disk_key.u.k_offset_v2.k_type; + return key->on_disk_key.k_type; } static inline void set_cpu_key_k_offset (struct cpu_key * key, loff_t offset) { - (key->version == KEY_FORMAT_3_5) ? - (key->on_disk_key.u.k_offset_v1.k_offset = offset) : - (key->on_disk_key.u.k_offset_v2.k_offset = offset); + key->on_disk_key.k_offset = offset; } - static inline void set_cpu_key_k_type (struct cpu_key * key, int type) { - (key->version == KEY_FORMAT_3_5) ? - (key->on_disk_key.u.k_offset_v1.k_uniqueness = type2uniqueness (type)): - (key->on_disk_key.u.k_offset_v2.k_type = type); + key->on_disk_key.k_type = type; } - static inline void cpu_key_k_offset_dec (struct cpu_key * key) { - if (key->version == KEY_FORMAT_3_5) - key->on_disk_key.u.k_offset_v1.k_offset --; - else - key->on_disk_key.u.k_offset_v2.k_offset --; + key->on_disk_key.k_offset --; } - #define is_direntry_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRENTRY) #define is_direct_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRECT) #define is_indirect_cpu_key(key) (cpu_key_k_type (key) == TYPE_INDIRECT) -- cgit v1.2.3 From fe55c452368af263a9beec38ed29f6be85280524 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Sun, 1 May 2005 08:59:20 -0700 Subject: [PATCH] ext3: remove unnecessary race then retry in ext3_get_block The extra race-with-truncate-then-retry logic around ext3_get_block_handle(), which was inherited from ext2, becomes unecessary for ext3, since we have already obtained the ei->truncate_sem in ext3_get_block_handle() before calling ext3_alloc_branch(). The ei->truncate_sem is already there to block concurrent truncate and block allocation on the same inode. So the inode's indirect addressing tree won't be changed after we grab that semaphore. We could, after get the semaphore, re-verify the branch is up-to-date or not. If it has been changed, then get the updated branch. If we still need block allocation, we will have a safe version of the branch to work with in the ext3_find_goal()/ext3_splice_branch(). The code becomes more readable after remove those retry logic. The patch also clean up some gotos in ext3_get_block_handle() to make it more readable. Signed-off-by: Mingming Cao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/inode.c | 144 ++++++++++++++++++++++++-------------------------------- 1 file changed, 61 insertions(+), 83 deletions(-) (limited to 'fs') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 040eb288bb1c..ea5888688f94 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -455,12 +455,11 @@ static unsigned long ext3_find_near(struct inode *inode, Indirect *ind) * @goal: place to store the result. * * Normally this function find the prefered place for block allocation, - * stores it in *@goal and returns zero. If the branch had been changed - * under us we return -EAGAIN. + * stores it in *@goal and returns zero. */ -static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], - Indirect *partial, unsigned long *goal) +static unsigned long ext3_find_goal(struct inode *inode, long block, + Indirect chain[4], Indirect *partial) { struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info; @@ -470,15 +469,10 @@ static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], */ if (block_i && (block == block_i->last_alloc_logical_block + 1) && (block_i->last_alloc_physical_block != 0)) { - *goal = block_i->last_alloc_physical_block + 1; - return 0; + return block_i->last_alloc_physical_block + 1; } - if (verify_chain(chain, partial)) { - *goal = ext3_find_near(inode, partial); - return 0; - } - return -EAGAIN; + return ext3_find_near(inode, partial); } /** @@ -582,12 +576,9 @@ static int ext3_alloc_branch(handle_t *handle, struct inode *inode, * @where: location of missing link * @num: number of blocks we are adding * - * This function verifies that chain (up to the missing link) had not - * changed, fills the missing link and does all housekeeping needed in + * This function fills the missing link and does all housekeeping needed in * inode (->i_blocks, etc.). In case of success we end up with the full - * chain to new block and return 0. Otherwise (== chain had been changed) - * we free the new blocks (forgetting their buffer_heads, indeed) and - * return -EAGAIN. + * chain to new block and return 0. */ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, @@ -608,12 +599,6 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, if (err) goto err_out; } - /* Verify that place we are splicing to is still there and vacant */ - - if (!verify_chain(chain, where-1) || *where->p) - /* Writer: end */ - goto changed; - /* That's it */ *where->p = where->key; @@ -657,26 +642,11 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, } return err; -changed: - /* - * AKPM: if where[i].bh isn't part of the current updating - * transaction then we explode nastily. Test this code path. - */ - jbd_debug(1, "the chain changed: try again\n"); - err = -EAGAIN; - err_out: for (i = 1; i < num; i++) { BUFFER_TRACE(where[i].bh, "call journal_forget"); ext3_journal_forget(handle, where[i].bh); } - /* For the normal collision cleanup case, we free up the blocks. - * On genuine filesystem errors we don't even think about doing - * that. */ - if (err == -EAGAIN) - for (i = 0; i < num; i++) - ext3_free_blocks(handle, inode, - le32_to_cpu(where[i].key), 1); return err; } @@ -708,7 +678,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, unsigned long goal; int left; int boundary = 0; - int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); + const int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); struct ext3_inode_info *ei = EXT3_I(inode); J_ASSERT(handle != NULL || create == 0); @@ -716,54 +686,55 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, if (depth == 0) goto out; -reread: partial = ext3_get_branch(inode, depth, offsets, chain, &err); /* Simplest case - block found, no allocation needed */ if (!partial) { clear_buffer_new(bh_result); -got_it: - map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); - if (boundary) - set_buffer_boundary(bh_result); - /* Clean up and exit */ - partial = chain+depth-1; /* the whole chain */ - goto cleanup; + goto got_it; } /* Next simple case - plain lookup or failed read of indirect block */ - if (!create || err == -EIO) { -cleanup: + if (!create || err == -EIO) + goto cleanup; + + down(&ei->truncate_sem); + + /* + * If the indirect block is missing while we are reading + * the chain(ext3_get_branch() returns -EAGAIN err), or + * if the chain has been changed after we grab the semaphore, + * (either because another process truncated this branch, or + * another get_block allocated this branch) re-grab the chain to see if + * the request block has been allocated or not. + * + * Since we already block the truncate/other get_block + * at this point, we will have the current copy of the chain when we + * splice the branch into the tree. + */ + if (err == -EAGAIN || !verify_chain(chain, partial)) { while (partial > chain) { - BUFFER_TRACE(partial->bh, "call brelse"); brelse(partial->bh); partial--; } - BUFFER_TRACE(bh_result, "returned"); -out: - return err; + partial = ext3_get_branch(inode, depth, offsets, chain, &err); + if (!partial) { + up(&ei->truncate_sem); + if (err) + goto cleanup; + clear_buffer_new(bh_result); + goto got_it; + } } /* - * Indirect block might be removed by truncate while we were - * reading it. Handling of that case (forget what we've got and - * reread) is taken out of the main path. - */ - if (err == -EAGAIN) - goto changed; - - goal = 0; - down(&ei->truncate_sem); - - /* lazy initialize the block allocation info here if necessary */ - if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) { + * Okay, we need to do block allocation. Lazily initialize the block + * allocation info here if necessary + */ + if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) ext3_init_block_alloc_info(inode); - } - if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) { - up(&ei->truncate_sem); - goto changed; - } + goal = ext3_find_goal(inode, iblock, chain, partial); left = (chain + depth) - partial; @@ -771,38 +742,45 @@ out: * Block out ext3_truncate while we alter the tree */ err = ext3_alloc_branch(handle, inode, left, goal, - offsets+(partial-chain), partial); + offsets + (partial - chain), partial); - /* The ext3_splice_branch call will free and forget any buffers + /* + * The ext3_splice_branch call will free and forget any buffers * on the new chain if there is a failure, but that risks using * up transaction credits, especially for bitmaps where the * credits cannot be returned. Can we handle this somehow? We - * may need to return -EAGAIN upwards in the worst case. --sct */ + * may need to return -EAGAIN upwards in the worst case. --sct + */ if (!err) err = ext3_splice_branch(handle, inode, iblock, chain, partial, left); - /* i_disksize growing is protected by truncate_sem - * don't forget to protect it if you're about to implement - * concurrent ext3_get_block() -bzzz */ + /* + * i_disksize growing is protected by truncate_sem. Don't forget to + * protect it if you're about to implement concurrent + * ext3_get_block() -bzzz + */ if (!err && extend_disksize && inode->i_size > ei->i_disksize) ei->i_disksize = inode->i_size; up(&ei->truncate_sem); - if (err == -EAGAIN) - goto changed; if (err) goto cleanup; set_buffer_new(bh_result); - goto got_it; - -changed: +got_it: + map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); + if (boundary) + set_buffer_boundary(bh_result); + /* Clean up and exit */ + partial = chain + depth - 1; /* the whole chain */ +cleanup: while (partial > chain) { - jbd_debug(1, "buffer chain changed, retrying\n"); - BUFFER_TRACE(partial->bh, "brelsing"); + BUFFER_TRACE(partial->bh, "call brelse"); brelse(partial->bh); partial--; } - goto reread; + BUFFER_TRACE(bh_result, "returned"); +out: + return err; } static int ext3_get_block(struct inode *inode, sector_t iblock, -- cgit v1.2.3 From 4dc3b16ba18c0f967ad100c52fa65b01a4f76ff0 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 1 May 2005 08:59:25 -0700 Subject: [PATCH] DocBook: changes and extensions to the kernel documentation I have recompiled Linux kernel 2.6.11.5 documentation for me and our university students again. The documentation could be extended for more sources which are equipped by structured comments for recent 2.6 kernels. I have tried to proceed with that task. I have done that more times from 2.6.0 time and it gets boring to do same changes again and again. Linux kernel compiles after changes for i386 and ARM targets. I have added references to some more files into kernel-api book, I have added some section names as well. So please, check that changes do not break something and that categories are not too much skewed. I have changed kernel-doc to accept "fastcall" and "asmlinkage" words reserved by kernel convention. Most of the other changes are modifications in the comments to make kernel-doc happy, accept some parameters description and do not bail out on errors. Changed to @pid in the description, moved some #ifdef before comments to correct function to comments bindings, etc. You can see result of the modified documentation build at http://cmp.felk.cvut.cz/~pisa/linux/lkdb-2.6.11.tar.gz Some more sources are ready to be included into kernel-doc generated documentation. Sources has been added into kernel-api for now. Some more section names added and probably some more chaos introduced as result of quick cleanup work. Signed-off-by: Pavel Pisa Signed-off-by: Martin Waitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 186 ++++++++++++++++++++++++++++++++-- drivers/video/fbmem.c | 5 +- fs/proc/base.c | 10 +- include/linux/fs.h | 12 +-- include/linux/net.h | 38 +++---- include/linux/skbuff.h | 2 +- include/net/sock.h | 134 ++++++++++++------------ kernel/exit.c | 2 +- kernel/power/swsusp.c | 2 +- mm/page_alloc.c | 3 +- mm/vmalloc.c | 8 +- net/core/datagram.c | 28 ++--- net/core/sock.c | 12 +-- net/core/stream.c | 12 +-- net/sunrpc/xdr.c | 12 +-- scripts/kernel-doc | 2 + 16 files changed, 320 insertions(+), 148 deletions(-) (limited to 'fs') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 1bd20c860285..757cef8f8491 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -49,13 +49,33 @@ !Iinclude/asm-i386/unaligned.h - + Internal Functions +!Ikernel/exit.c +!Ikernel/signal.c + + + Kernel objects manipulation + +!Elib/kobject.c + + + Kernel utility functions +!Iinclude/linux/kernel.h + +!Ekernel/panic.c +!Ekernel/sys.c +!Ekernel/rcupdate.c + + @@ -81,7 +101,9 @@ KAO --> !Elib/vsprintf.c String Manipulation -!Ilib/string.c + !Elib/string.c Bit Operations @@ -98,6 +120,25 @@ KAO --> !Iinclude/asm-i386/uaccess.h !Iarch/i386/lib/usercopy.c + More Memory Management Functions +!Iinclude/linux/rmap.h +!Emm/readahead.c +!Emm/filemap.c +!Emm/memory.c +!Emm/vmalloc.c +!Emm/mempool.c +!Emm/page-writeback.c +!Emm/truncate.c + + + + + + Kernel IPC facilities + + IPC utilities +!Iipc/util.c + @@ -114,6 +155,10 @@ KAO --> sysctl interface !Ekernel/sysctl.c + + proc filesystem interface +!Ifs/proc/base.c + @@ -127,6 +172,10 @@ KAO --> The Linux VFS + The Filesystem types +!Iinclude/linux/fs.h +!Einclude/linux/fs.h + The Directory Cache !Efs/dcache.c !Iinclude/linux/dcache.h @@ -142,13 +191,31 @@ KAO --> !Efs/locks.c !Ifs/locks.c + Other Functions +!Efs/mpage.c +!Efs/namei.c +!Efs/buffer.c +!Efs/bio.c +!Efs/seq_file.c +!Efs/filesystems.c +!Efs/fs-writeback.c +!Efs/block_dev.c + Linux Networking + Networking Base Types +!Iinclude/linux/net.h + Socket Buffer Functions !Iinclude/linux/skbuff.h +!Iinclude/net/sock.h +!Enet/socket.c !Enet/core/skbuff.c +!Enet/core/sock.c +!Enet/core/datagram.c +!Enet/core/stream.c Socket Filter !Enet/core/filter.c @@ -158,6 +225,14 @@ KAO --> !Enet/core/gen_stats.c !Enet/core/gen_estimator.c + SUN RPC subsystem + +!Enet/sunrpc/xdr.c +!Enet/sunrpc/svcsock.c +!Enet/sunrpc/sched.c + @@ -194,11 +269,26 @@ X!Ekernel/module.c !Iarch/i386/kernel/irq.c + Resources Management +!Ekernel/resource.c + + MTRR Handling !Earch/i386/kernel/cpu/mtrr/main.c PCI Support Library !Edrivers/pci/pci.c +!Edrivers/pci/pci-driver.c +!Edrivers/pci/remove.c +!Edrivers/pci/pci-acpi.c + +!Edrivers/pci/msi.c +!Edrivers/pci/bus.c +!Edrivers/pci/hotplug.c +!Edrivers/pci/probe.c +!Edrivers/pci/rom.c PCI Hotplug Support Library !Edrivers/pci/hotplug/pci_hotplug_core.c @@ -223,6 +313,14 @@ X!Earch/i386/kernel/mca.c !Efs/devfs/base.c + + The Filesystem for Exporting Kernel Objects +!Efs/sysfs/file.c +!Efs/sysfs/dir.c +!Efs/sysfs/symlink.c +!Efs/sysfs/bin.c + + Security Framework !Esecurity/security.c @@ -233,6 +331,61 @@ X!Earch/i386/kernel/mca.c !Ekernel/power/pm.c + + Device drivers infrastructure + Device Drivers Base + +!Edrivers/base/driver.c +!Edrivers/base/class_simple.c +!Edrivers/base/core.c +!Edrivers/base/firmware_class.c +!Edrivers/base/transport_class.c +!Edrivers/base/dmapool.c + +!Edrivers/base/sys.c + +!Edrivers/base/platform.c +!Edrivers/base/bus.c + + Device Drivers Power Management +!Edrivers/base/power/main.c +!Edrivers/base/power/resume.c +!Edrivers/base/power/suspend.c + + Device Drivers ACPI Support + +!Edrivers/acpi/scan.c + + + Device drivers PnP support +!Edrivers/pnp/core.c + +!Edrivers/pnp/card.c +!Edrivers/pnp/driver.c +!Edrivers/pnp/manager.c +!Edrivers/pnp/support.c + + + + Block Devices !Edrivers/block/ll_rw_blk.c @@ -250,7 +403,23 @@ X!Earch/i386/kernel/mca.c Sound Devices +!Iinclude/sound/core.h !Esound/sound_core.c +!Iinclude/sound/pcm.h +!Esound/core/pcm.c +!Esound/core/device.c +!Esound/core/info.c +!Esound/core/rawmidi.c +!Esound/core/sound.c +!Esound/core/memory.c +!Esound/core/pcm_memory.c +!Esound/core/init.c +!Esound/core/isadma.c +!Esound/core/control.c +!Esound/core/pcm_lib.c +!Esound/core/hwdep.c +!Esound/core/pcm_native.c +!Esound/core/memalloc.c @@ -258,6 +427,7 @@ X!Isound/sound_firmware.c 16x50 UART Driver +!Iinclude/linux/serial_core.h !Edrivers/serial/serial_core.c !Edrivers/serial/8250.c @@ -310,9 +480,11 @@ X!Isound/sound_firmware.c Frame Buffer Memory !Edrivers/video/fbmem.c + Frame Buffer Colormap !Edrivers/video/fbcmap.c diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 25f460ca0daf..208a68ceb63b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1257,6 +1257,8 @@ int fb_new_modelist(struct fb_info *info) static char *video_options[FB_MAX]; static int ofonly; +extern const char *global_mode_option; + /** * fb_get_options - get kernel boot parameters * @name: framebuffer name as it would appear in @@ -1297,9 +1299,6 @@ int fb_get_options(char *name, char **option) return retval; } - -extern const char *global_mode_option; - /** * video_setup - process command line options * @options: string of options diff --git a/fs/proc/base.c b/fs/proc/base.c index 2eac86d46c51..2b8cd045111c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1703,13 +1703,13 @@ static struct inode_operations proc_self_inode_operations = { }; /** - * proc_pid_unhash - Unhash /proc/ entry from the dcache. + * proc_pid_unhash - Unhash /proc/@pid entry from the dcache. * @p: task that should be flushed. * - * Drops the /proc/ dcache entry from the hash chains. + * Drops the /proc/@pid dcache entry from the hash chains. * - * Dropping /proc/ entries and detach_pid must be synchroneous, - * otherwise e.g. /proc//exe might point to the wrong executable, + * Dropping /proc/@pid entries and detach_pid must be synchroneous, + * otherwise e.g. /proc/@pid/exe might point to the wrong executable, * if the pid value is immediately reused. This is enforced by * - caller must acquire spin_lock(p->proc_lock) * - must be called before detach_pid() @@ -1741,7 +1741,7 @@ struct dentry *proc_pid_unhash(struct task_struct *p) } /** - * proc_pid_flush - recover memory used by stale /proc//x entries + * proc_pid_flush - recover memory used by stale /proc/@pid/x entries * @proc_entry: directoy to prune. * * Shrink the /proc directory that was used by the just killed thread. diff --git a/include/linux/fs.h b/include/linux/fs.h index 5df687d940fa..3f825b085c8d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1053,12 +1053,12 @@ static inline void file_accessed(struct file *file) int sync_inode(struct inode *inode, struct writeback_control *wbc); /** - * &export_operations - for nfsd to communicate with file systems - * decode_fh: decode a file handle fragment and return a &struct dentry - * encode_fh: encode a file handle fragment from a dentry - * get_name: find the name for a given inode in a given directory - * get_parent: find the parent of a given directory - * get_dentry: find a dentry for the inode given a file handle sub-fragment + * struct export_operations - for nfsd to communicate with file systems + * @decode_fh: decode a file handle fragment and return a &struct dentry + * @encode_fh: encode a file handle fragment from a dentry + * @get_name: find the name for a given inode in a given directory + * @get_parent: find the parent of a given directory + * @get_dentry: find a dentry for the inode given a file handle sub-fragment * * Description: * The export_operations structure provides a means for nfsd to communicate diff --git a/include/linux/net.h b/include/linux/net.h index 7823b3482506..e5914c1f0c4d 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -64,19 +64,19 @@ typedef enum { #define SOCK_PASSCRED 3 #ifndef ARCH_HAS_SOCKET_TYPES -/** sock_type - Socket types - * +/** + * enum sock_type - Socket types + * @SOCK_STREAM: stream (connection) socket + * @SOCK_DGRAM: datagram (conn.less) socket + * @SOCK_RAW: raw socket + * @SOCK_RDM: reliably-delivered message + * @SOCK_SEQPACKET: sequential packet socket + * @SOCK_PACKET: linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user level. + * * When adding some new socket type please * grep ARCH_HAS_SOCKET_TYPE include/asm-* /socket.h, at least MIPS * overrides this enum for binary compat reasons. - * - * @SOCK_STREAM - stream (connection) socket - * @SOCK_DGRAM - datagram (conn.less) socket - * @SOCK_RAW - raw socket - * @SOCK_RDM - reliably-delivered message - * @SOCK_SEQPACKET - sequential packet socket - * @SOCK_PACKET - linux specific way of getting packets at the dev level. - * For writing rarp and other similar things on the user level. */ enum sock_type { SOCK_STREAM = 1, @@ -93,15 +93,15 @@ enum sock_type { /** * struct socket - general BSD socket - * @state - socket state (%SS_CONNECTED, etc) - * @flags - socket flags (%SOCK_ASYNC_NOSPACE, etc) - * @ops - protocol specific socket operations - * @fasync_list - Asynchronous wake up list - * @file - File back pointer for gc - * @sk - internal networking protocol agnostic socket representation - * @wait - wait queue for several uses - * @type - socket type (%SOCK_STREAM, etc) - * @passcred - credentials (used only in Unix Sockets (aka PF_LOCAL)) + * @state: socket state (%SS_CONNECTED, etc) + * @flags: socket flags (%SOCK_ASYNC_NOSPACE, etc) + * @ops: protocol specific socket operations + * @fasync_list: Asynchronous wake up list + * @file: File back pointer for gc + * @sk: internal networking protocol agnostic socket representation + * @wait: wait queue for several uses + * @type: socket type (%SOCK_STREAM, etc) + * @passcred: credentials (used only in Unix Sockets (aka PF_LOCAL)) */ struct socket { socket_state state; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 22b701819619..c77d745cbd3f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -968,6 +968,7 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) kfree_skb(skb); } +#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB /** * __dev_alloc_skb - allocate an skbuff for sending * @length: length to allocate @@ -980,7 +981,6 @@ static inline void __skb_queue_purge(struct sk_buff_head *list) * * %NULL is returned in there is no free memory. */ -#ifndef CONFIG_HAVE_ARCH_DEV_ALLOC_SKB static inline struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask) { diff --git a/include/net/sock.h b/include/net/sock.h index be81cabd0da3..5bc180adfb14 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -90,17 +90,17 @@ do { spin_lock_init(&((__sk)->sk_lock.slock)); \ struct sock; /** - * struct sock_common - minimal network layer representation of sockets - * @skc_family - network address family - * @skc_state - Connection state - * @skc_reuse - %SO_REUSEADDR setting - * @skc_bound_dev_if - bound device index if != 0 - * @skc_node - main hash linkage for various protocol lookup tables - * @skc_bind_node - bind hash linkage for various protocol lookup tables - * @skc_refcnt - reference count - * - * This is the minimal network layer representation of sockets, the header - * for struct sock and struct tcp_tw_bucket. + * struct sock_common - minimal network layer representation of sockets + * @skc_family: network address family + * @skc_state: Connection state + * @skc_reuse: %SO_REUSEADDR setting + * @skc_bound_dev_if: bound device index if != 0 + * @skc_node: main hash linkage for various protocol lookup tables + * @skc_bind_node: bind hash linkage for various protocol lookup tables + * @skc_refcnt: reference count + * + * This is the minimal network layer representation of sockets, the header + * for struct sock and struct tcp_tw_bucket. */ struct sock_common { unsigned short skc_family; @@ -114,60 +114,60 @@ struct sock_common { /** * struct sock - network layer representation of sockets - * @__sk_common - shared layout with tcp_tw_bucket - * @sk_shutdown - mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN - * @sk_userlocks - %SO_SNDBUF and %SO_RCVBUF settings - * @sk_lock - synchronizer - * @sk_rcvbuf - size of receive buffer in bytes - * @sk_sleep - sock wait queue - * @sk_dst_cache - destination cache - * @sk_dst_lock - destination cache lock - * @sk_policy - flow policy - * @sk_rmem_alloc - receive queue bytes committed - * @sk_receive_queue - incoming packets - * @sk_wmem_alloc - transmit queue bytes committed - * @sk_write_queue - Packet sending queue - * @sk_omem_alloc - "o" is "option" or "other" - * @sk_wmem_queued - persistent queue size - * @sk_forward_alloc - space allocated forward - * @sk_allocation - allocation mode - * @sk_sndbuf - size of send buffer in bytes - * @sk_flags - %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings - * @sk_no_check - %SO_NO_CHECK setting, wether or not checkup packets - * @sk_route_caps - route capabilities (e.g. %NETIF_F_TSO) - * @sk_lingertime - %SO_LINGER l_linger setting - * @sk_hashent - hash entry in several tables (e.g. tcp_ehash) - * @sk_backlog - always used with the per-socket spinlock held - * @sk_callback_lock - used with the callbacks in the end of this struct - * @sk_error_queue - rarely used - * @sk_prot - protocol handlers inside a network family - * @sk_err - last error - * @sk_err_soft - errors that don't cause failure but are the cause of a persistent failure not just 'timed out' - * @sk_ack_backlog - current listen backlog - * @sk_max_ack_backlog - listen backlog set in listen() - * @sk_priority - %SO_PRIORITY setting - * @sk_type - socket type (%SOCK_STREAM, etc) - * @sk_protocol - which protocol this socket belongs in this network family - * @sk_peercred - %SO_PEERCRED setting - * @sk_rcvlowat - %SO_RCVLOWAT setting - * @sk_rcvtimeo - %SO_RCVTIMEO setting - * @sk_sndtimeo - %SO_SNDTIMEO setting - * @sk_filter - socket filtering instructions - * @sk_protinfo - private area, net family specific, when not using slab - * @sk_timer - sock cleanup timer - * @sk_stamp - time stamp of last packet received - * @sk_socket - Identd and reporting IO signals - * @sk_user_data - RPC layer private data - * @sk_sndmsg_page - cached page for sendmsg - * @sk_sndmsg_off - cached offset for sendmsg - * @sk_send_head - front of stuff to transmit - * @sk_write_pending - a write to stream socket waits to start - * @sk_state_change - callback to indicate change in the state of the sock - * @sk_data_ready - callback to indicate there is data to be processed - * @sk_write_space - callback to indicate there is bf sending space available - * @sk_error_report - callback to indicate errors (e.g. %MSG_ERRQUEUE) - * @sk_backlog_rcv - callback to process the backlog - * @sk_destruct - called at sock freeing time, i.e. when all refcnt == 0 + * @__sk_common: shared layout with tcp_tw_bucket + * @sk_shutdown: mask of %SEND_SHUTDOWN and/or %RCV_SHUTDOWN + * @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings + * @sk_lock: synchronizer + * @sk_rcvbuf: size of receive buffer in bytes + * @sk_sleep: sock wait queue + * @sk_dst_cache: destination cache + * @sk_dst_lock: destination cache lock + * @sk_policy: flow policy + * @sk_rmem_alloc: receive queue bytes committed + * @sk_receive_queue: incoming packets + * @sk_wmem_alloc: transmit queue bytes committed + * @sk_write_queue: Packet sending queue + * @sk_omem_alloc: "o" is "option" or "other" + * @sk_wmem_queued: persistent queue size + * @sk_forward_alloc: space allocated forward + * @sk_allocation: allocation mode + * @sk_sndbuf: size of send buffer in bytes + * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings + * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets + * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) + * @sk_lingertime: %SO_LINGER l_linger setting + * @sk_hashent: hash entry in several tables (e.g. tcp_ehash) + * @sk_backlog: always used with the per-socket spinlock held + * @sk_callback_lock: used with the callbacks in the end of this struct + * @sk_error_queue: rarely used + * @sk_prot: protocol handlers inside a network family + * @sk_err: last error + * @sk_err_soft: errors that don't cause failure but are the cause of a persistent failure not just 'timed out' + * @sk_ack_backlog: current listen backlog + * @sk_max_ack_backlog: listen backlog set in listen() + * @sk_priority: %SO_PRIORITY setting + * @sk_type: socket type (%SOCK_STREAM, etc) + * @sk_protocol: which protocol this socket belongs in this network family + * @sk_peercred: %SO_PEERCRED setting + * @sk_rcvlowat: %SO_RCVLOWAT setting + * @sk_rcvtimeo: %SO_RCVTIMEO setting + * @sk_sndtimeo: %SO_SNDTIMEO setting + * @sk_filter: socket filtering instructions + * @sk_protinfo: private area, net family specific, when not using slab + * @sk_timer: sock cleanup timer + * @sk_stamp: time stamp of last packet received + * @sk_socket: Identd and reporting IO signals + * @sk_user_data: RPC layer private data + * @sk_sndmsg_page: cached page for sendmsg + * @sk_sndmsg_off: cached offset for sendmsg + * @sk_send_head: front of stuff to transmit + * @sk_write_pending: a write to stream socket waits to start + * @sk_state_change: callback to indicate change in the state of the sock + * @sk_data_ready: callback to indicate there is data to be processed + * @sk_write_space: callback to indicate there is bf sending space available + * @sk_error_report: callback to indicate errors (e.g. %MSG_ERRQUEUE) + * @sk_backlog_rcv: callback to process the backlog + * @sk_destruct: called at sock freeing time, i.e. when all refcnt == 0 */ struct sock { /* @@ -1223,8 +1223,8 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) /** * sk_eat_skb - Release a skb if it is no longer needed - * @sk - socket to eat this skb from - * @skb - socket buffer to eat + * @sk: socket to eat this skb from + * @skb: socket buffer to eat * * This routine must be called with interrupts disabled or with the socket * locked so that the sk_buff queue operation is ok. diff --git a/kernel/exit.c b/kernel/exit.c index eb8da36e13df..419d9d3c4c48 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -210,7 +210,7 @@ static inline int has_stopped_jobs(int pgrp) } /** - * reparent_to_init() - Reparent the calling kernel thread to the init task. + * reparent_to_init - Reparent the calling kernel thread to the init task. * * If a kernel thread is launched as a result of a system call, or if * it ever exits, it should generally reparent itself to init so that diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c index ae5bebc3b18f..90b3b68dee3f 100644 --- a/kernel/power/swsusp.c +++ b/kernel/power/swsusp.c @@ -1099,7 +1099,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist) return pblist; } -/** +/* * Using bio to read from swap. * This code requires a bit more work than just using buffer heads * but, it is the recommended way for 2.5/2.6. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 80ce7f2104df..fc1b1064c505 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1355,8 +1355,7 @@ static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zoneli #define MAX_NODE_LOAD (num_online_nodes()) static int __initdata node_load[MAX_NUMNODES]; /** - * find_next_best_node - find the next node that should appear in a given - * node's fallback list + * find_next_best_node - find the next node that should appear in a given node's fallback list * @node: node whose fallback list we're appending * @used_node_mask: nodemask_t of already used nodes * diff --git a/mm/vmalloc.c b/mm/vmalloc.c index c6182f6f1305..2bd83e5c2bbf 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -475,6 +475,10 @@ void *vmalloc(unsigned long size) EXPORT_SYMBOL(vmalloc); +#ifndef PAGE_KERNEL_EXEC +# define PAGE_KERNEL_EXEC PAGE_KERNEL +#endif + /** * vmalloc_exec - allocate virtually contiguous, executable memory * @@ -488,10 +492,6 @@ EXPORT_SYMBOL(vmalloc); * use __vmalloc() instead. */ -#ifndef PAGE_KERNEL_EXEC -# define PAGE_KERNEL_EXEC PAGE_KERNEL -#endif - void *vmalloc_exec(unsigned long size) { return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC); diff --git a/net/core/datagram.c b/net/core/datagram.c index d1bfd279cc1a..27c5cd942820 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -115,10 +115,10 @@ out_noerr: /** * skb_recv_datagram - Receive a datagram skbuff - * @sk - socket - * @flags - MSG_ flags - * @noblock - blocking operation? - * @err - error code returned + * @sk: socket + * @flags: MSG_ flags + * @noblock: blocking operation? + * @err: error code returned * * Get a datagram skbuff, understands the peeking, nonblocking wakeups * and possible races. This replaces identical code in packet, raw and @@ -201,10 +201,10 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) /** * skb_copy_datagram_iovec - Copy a datagram to an iovec. - * @skb - buffer to copy - * @offset - offset in the buffer to start copying from - * @iovec - io vector to copy to - * @len - amount of data to copy from buffer to iovec + * @skb: buffer to copy + * @offset: offset in the buffer to start copying from + * @iovec: io vector to copy to + * @len: amount of data to copy from buffer to iovec * * Note: the iovec is modified during the copy. */ @@ -377,9 +377,9 @@ fault: /** * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. - * @skb - skbuff - * @hlen - hardware length - * @iovec - io vector + * @skb: skbuff + * @hlen: hardware length + * @iovec: io vector * * Caller _must_ check that skb will fit to this iovec. * @@ -425,9 +425,9 @@ fault: /** * datagram_poll - generic datagram poll - * @file - file struct - * @sock - socket - * @wait - poll table + * @file: file struct + * @sock: socket + * @wait: poll table * * Datagram poll: Again totally generic. This also handles * sequenced packet sockets providing the socket receive queue diff --git a/net/core/sock.c b/net/core/sock.c index 5c2f72fa1013..98171ddd7e7d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -616,10 +616,10 @@ lenout: /** * sk_alloc - All socket objects are allocated here - * @family - protocol family - * @priority - for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) - * @prot - struct proto associated with this new sock instance - * @zero_it - if we should zero the newly allocated sock + * @family: protocol family + * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc) + * @prot: struct proto associated with this new sock instance + * @zero_it: if we should zero the newly allocated sock */ struct sock *sk_alloc(int family, int priority, struct proto *prot, int zero_it) { @@ -970,8 +970,8 @@ static void __release_sock(struct sock *sk) /** * sk_wait_data - wait for data to arrive at sk_receive_queue - * sk - sock to wait on - * timeo - for how long + * @sk: sock to wait on + * @timeo: for how long * * Now socket state including sk->sk_err is changed only under lock, * hence we may omit checks after joining wait queue. diff --git a/net/core/stream.c b/net/core/stream.c index 1e27a57b5a97..ac9edfdf8742 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -21,7 +21,7 @@ /** * sk_stream_write_space - stream socket write_space callback. - * sk - socket + * @sk: socket * * FIXME: write proper description */ @@ -43,8 +43,8 @@ EXPORT_SYMBOL(sk_stream_write_space); /** * sk_stream_wait_connect - Wait for a socket to get into the connected state - * @sk - sock to wait on - * @timeo_p - for how long to wait + * @sk: sock to wait on + * @timeo_p: for how long to wait * * Must be called with the socket locked. */ @@ -79,7 +79,7 @@ EXPORT_SYMBOL(sk_stream_wait_connect); /** * sk_stream_closing - Return 1 if we still have things to send in our buffers. - * @sk - socket to verify + * @sk: socket to verify */ static inline int sk_stream_closing(struct sock *sk) { @@ -107,8 +107,8 @@ EXPORT_SYMBOL(sk_stream_wait_close); /** * sk_stream_wait_memory - Wait for more memory for a socket - * @sk - socket to wait for memory - * @timeo_p - for how long + * @sk: socket to wait for memory + * @timeo_p: for how long */ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) { diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 4484931018eb..67b9f035ba86 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -46,9 +46,9 @@ xdr_decode_netobj(u32 *p, struct xdr_netobj *obj) /** * xdr_encode_opaque_fixed - Encode fixed length opaque data - * @p - pointer to current position in XDR buffer. - * @ptr - pointer to data to encode (or NULL) - * @nbytes - size of data. + * @p: pointer to current position in XDR buffer. + * @ptr: pointer to data to encode (or NULL) + * @nbytes: size of data. * * Copy the array of data of length nbytes at ptr to the XDR buffer * at position p, then align to the next 32-bit boundary by padding @@ -76,9 +76,9 @@ EXPORT_SYMBOL(xdr_encode_opaque_fixed); /** * xdr_encode_opaque - Encode variable length opaque data - * @p - pointer to current position in XDR buffer. - * @ptr - pointer to data to encode (or NULL) - * @nbytes - size of data. + * @p: pointer to current position in XDR buffer. + * @ptr: pointer to data to encode (or NULL) + * @nbytes: size of data. * * Returns the updated current XDR buffer position */ diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 8b1dab63f11c..3cc333070e59 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1465,6 +1465,8 @@ sub dump_function($$) { $prototype =~ s/^static +//; $prototype =~ s/^extern +//; + $prototype =~ s/^fastcall +//; + $prototype =~ s/^asmlinkage +//; $prototype =~ s/^inline +//; $prototype =~ s/^__inline__ +//; $prototype =~ s/^#define +//; #ak added -- cgit v1.2.3 From 67be2dd1bace0ec7ce2dbc1bba3f8df3d7be597e Mon Sep 17 00:00:00 2001 From: Martin Waitz Date: Sun, 1 May 2005 08:59:26 -0700 Subject: [PATCH] DocBook: fix some descriptions Some KernelDoc descriptions are updated to match the current code. No code changes. Signed-off-by: Martin Waitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/scan.c | 4 +- drivers/base/platform.c | 4 +- drivers/pci/hotplug.c | 4 ++ drivers/pci/rom.c | 14 +++---- drivers/pnp/manager.c | 2 +- fs/bio.c | 2 + fs/buffer.c | 11 +++--- fs/fs-writeback.c | 4 +- fs/mpage.c | 92 ++++++++++++++++++++++---------------------- fs/proc/base.c | 2 +- fs/seq_file.c | 9 ++++- fs/sysfs/file.c | 4 +- include/linux/fs.h | 100 +++++++++++++++++++++++++----------------------- include/linux/skbuff.h | 5 ++- include/net/sock.h | 1 + kernel/sched.c | 3 +- kernel/sysctl.c | 2 + lib/kobject.c | 3 +- mm/filemap.c | 17 ++++---- mm/page-writeback.c | 6 +-- mm/truncate.c | 4 +- net/core/datagram.c | 4 +- 22 files changed, 160 insertions(+), 137 deletions(-) (limited to 'fs') diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index e7ca06626566..119c94093a13 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -379,8 +379,8 @@ ACPI_DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); /** * setup_sys_fs_device_files - sets up the device files under device namespace - * @@dev: acpi_device object - * @@func: function pointer to create or destroy the device file + * @dev: acpi_device object + * @func: function pointer to create or destroy the device file */ static void setup_sys_fs_device_files ( diff --git a/drivers/base/platform.c b/drivers/base/platform.c index cd6453905a9b..3a5f4c991797 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -115,7 +115,7 @@ int platform_add_devices(struct platform_device **devs, int num) /** * platform_device_register - add a platform-level device - * @dev: platform device we're adding + * @pdev: platform device we're adding * */ int platform_device_register(struct platform_device * pdev) @@ -174,7 +174,7 @@ int platform_device_register(struct platform_device * pdev) /** * platform_device_unregister - remove a platform-level device - * @dev: platform device we're removing + * @pdev: platform device we're removing * * Note that this function will also release all memory- and port-based * resources owned by the device (@dev->resource). diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c index d471b3ea5d12..021d0f76bc4c 100644 --- a/drivers/pci/hotplug.c +++ b/drivers/pci/hotplug.c @@ -120,6 +120,10 @@ static int pci_visit_bridge (struct pci_visit * fn, /** * pci_visit_dev - scans the pci buses. + * @fn: callback functions that are called while visiting + * @wrapped_dev: the device to scan + * @wrapped_parent: the bus where @wrapped_dev is connected to + * * Every bus and every function is presented to a custom * function that can act upon it. */ diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 3e64ff64b38c..838575e3fac6 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -14,7 +14,7 @@ /** * pci_enable_rom - enable ROM decoding for a PCI device - * @dev: PCI device to enable + * @pdev: PCI device to enable * * Enable ROM decoding on @dev. This involves simply turning on the last * bit of the PCI ROM BAR. Note that some cards may share address decoders @@ -32,7 +32,7 @@ static void pci_enable_rom(struct pci_dev *pdev) /** * pci_disable_rom - disable ROM decoding for a PCI device - * @dev: PCI device to disable + * @pdev: PCI device to disable * * Disable ROM decoding on a PCI device by turning off the last bit in the * ROM BAR. @@ -47,7 +47,7 @@ static void pci_disable_rom(struct pci_dev *pdev) /** * pci_map_rom - map a PCI ROM to kernel space - * @dev: pointer to pci device struct + * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM * @return: kernel virtual pointer to image of ROM * @@ -132,7 +132,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) /** * pci_map_rom_copy - map a PCI ROM to kernel space, create a copy - * @dev: pointer to pci device struct + * @pdev: pointer to pci device struct * @size: pointer to receive size of pci window over ROM * @return: kernel virtual pointer to image of ROM * @@ -166,7 +166,7 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) /** * pci_unmap_rom - unmap the ROM from kernel space - * @dev: pointer to pci device struct + * @pdev: pointer to pci device struct * @rom: virtual address of the previous mapping * * Remove a mapping of a previously mapped ROM @@ -187,7 +187,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) /** * pci_remove_rom - disable the ROM and remove its sysfs attribute - * @dev: pointer to pci device struct + * @pdev: pointer to pci device struct * * Remove the rom file in sysfs and disable ROM decoding. */ @@ -206,7 +206,7 @@ void pci_remove_rom(struct pci_dev *pdev) /** * pci_cleanup_rom - internal routine for freeing the ROM copy created * by pci_map_rom_copy called from remove.c - * @dev: pointer to pci device struct + * @pdev: pointer to pci device struct * * Free the copied ROM if we allocated one. */ diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 639e04253482..65ecef738537 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -253,7 +253,7 @@ void pnp_init_resource_table(struct pnp_resource_table *table) /** * pnp_clean_resources - clears resources that were not manually set - * @res - the resources to clean + * @res: the resources to clean * */ static void pnp_clean_resource_table(struct pnp_resource_table * res) diff --git a/fs/bio.c b/fs/bio.c index e5349e834563..3a1472acc361 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -140,6 +140,7 @@ inline void bio_init(struct bio *bio) * bio_alloc_bioset - allocate a bio for I/O * @gfp_mask: the GFP_ mask given to the slab allocator * @nr_iovecs: number of iovecs to pre-allocate + * @bs: the bio_set to allocate from * * Description: * bio_alloc_bioset will first try it's on mempool to satisfy the allocation. @@ -629,6 +630,7 @@ out: /** * bio_map_user - map user address into bio + * @q: the request_queue_t for the bio * @bdev: destination block device * @uaddr: start of user address * @len: length in bytes diff --git a/fs/buffer.c b/fs/buffer.c index 792cbacbbf41..5f525b3c6d9f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -774,15 +774,14 @@ repeat: /** * sync_mapping_buffers - write out and wait upon a mapping's "associated" * buffers - * @buffer_mapping - the mapping which backs the buffers' data - * @mapping - the mapping which wants those buffers written + * @mapping: the mapping which wants those buffers written * * Starts I/O against the buffers at mapping->private_list, and waits upon * that I/O. * - * Basically, this is a convenience function for fsync(). @buffer_mapping is - * the blockdev which "owns" the buffers and @mapping is a file or directory - * which needs those buffers to be written for a successful fsync(). + * Basically, this is a convenience function for fsync(). + * @mapping is a file or directory which needs those buffers to be written for + * a successful fsync(). */ int sync_mapping_buffers(struct address_space *mapping) { @@ -1263,6 +1262,7 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) /** * mark_buffer_dirty - mark a buffer_head as needing writeout + * @bh: the buffer_head to mark dirty * * mark_buffer_dirty() will set the dirty bit against the buffer, then set its * backing page dirty, then tag the page as dirty in its address_space's radix @@ -1501,6 +1501,7 @@ EXPORT_SYMBOL(__breadahead); /** * __bread() - reads a specified block and returns the bh + * @bdev: the block_device to read from * @block: number of block * @size: size (in bytes) to read * diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index d6efb36cab2a..8e050fa58218 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -512,7 +512,8 @@ restart: } /** - * sync_inodes + * sync_inodes - writes all inodes to disk + * @wait: wait for completion * * sync_inodes() goes through each super block's dirty inode list, writes the * inodes out, waits on the writeout and puts the inodes back on the normal @@ -604,6 +605,7 @@ EXPORT_SYMBOL(sync_inode); /** * generic_osync_inode - flush all dirty data for a given inode to disk * @inode: inode to write + * @mapping: the address_space that should be flushed * @what: what to write and wait upon * * This can be called by file_write functions for files which have the diff --git a/fs/mpage.c b/fs/mpage.c index 3923facf94eb..32c7c8fcfce7 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -160,52 +160,6 @@ map_buffer_to_page(struct page *page, struct buffer_head *bh, int page_block) } while (page_bh != head); } -/** - * mpage_readpages - populate an address space with some pages, and - * start reads against them. - * - * @mapping: the address_space - * @pages: The address of a list_head which contains the target pages. These - * pages have their ->index populated and are otherwise uninitialised. - * - * The page at @pages->prev has the lowest file offset, and reads should be - * issued in @pages->prev to @pages->next order. - * - * @nr_pages: The number of pages at *@pages - * @get_block: The filesystem's block mapper function. - * - * This function walks the pages and the blocks within each page, building and - * emitting large BIOs. - * - * If anything unusual happens, such as: - * - * - encountering a page which has buffers - * - encountering a page which has a non-hole after a hole - * - encountering a page with non-contiguous blocks - * - * then this code just gives up and calls the buffer_head-based read function. - * It does handle a page which has holes at the end - that is a common case: - * the end-of-file on blocksize < PAGE_CACHE_SIZE setups. - * - * BH_Boundary explanation: - * - * There is a problem. The mpage read code assembles several pages, gets all - * their disk mappings, and then submits them all. That's fine, but obtaining - * the disk mappings may require I/O. Reads of indirect blocks, for example. - * - * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be - * submitted in the following order: - * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 - * because the indirect block has to be read to get the mappings of blocks - * 13,14,15,16. Obviously, this impacts performance. - * - * So what we do it to allow the filesystem's get_block() function to set - * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block - * after this one will require I/O against a block which is probably close to - * this one. So you should push what I/O you have currently accumulated. - * - * This all causes the disk requests to be issued in the correct order. - */ static struct bio * do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, sector_t *last_block_in_bio, get_block_t get_block) @@ -320,6 +274,52 @@ confused: goto out; } +/** + * mpage_readpages - populate an address space with some pages, and + * start reads against them. + * + * @mapping: the address_space + * @pages: The address of a list_head which contains the target pages. These + * pages have their ->index populated and are otherwise uninitialised. + * + * The page at @pages->prev has the lowest file offset, and reads should be + * issued in @pages->prev to @pages->next order. + * + * @nr_pages: The number of pages at *@pages + * @get_block: The filesystem's block mapper function. + * + * This function walks the pages and the blocks within each page, building and + * emitting large BIOs. + * + * If anything unusual happens, such as: + * + * - encountering a page which has buffers + * - encountering a page which has a non-hole after a hole + * - encountering a page with non-contiguous blocks + * + * then this code just gives up and calls the buffer_head-based read function. + * It does handle a page which has holes at the end - that is a common case: + * the end-of-file on blocksize < PAGE_CACHE_SIZE setups. + * + * BH_Boundary explanation: + * + * There is a problem. The mpage read code assembles several pages, gets all + * their disk mappings, and then submits them all. That's fine, but obtaining + * the disk mappings may require I/O. Reads of indirect blocks, for example. + * + * So an mpage read of the first 16 blocks of an ext2 file will cause I/O to be + * submitted in the following order: + * 12 0 1 2 3 4 5 6 7 8 9 10 11 13 14 15 16 + * because the indirect block has to be read to get the mappings of blocks + * 13,14,15,16. Obviously, this impacts performance. + * + * So what we do it to allow the filesystem's get_block() function to set + * BH_Boundary when it maps block 11. BH_Boundary says: mapping of the block + * after this one will require I/O against a block which is probably close to + * this one. So you should push what I/O you have currently accumulated. + * + * This all causes the disk requests to be issued in the correct order. + */ int mpage_readpages(struct address_space *mapping, struct list_head *pages, unsigned nr_pages, get_block_t get_block) diff --git a/fs/proc/base.c b/fs/proc/base.c index 2b8cd045111c..07cafdf74ef2 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1742,7 +1742,7 @@ struct dentry *proc_pid_unhash(struct task_struct *p) /** * proc_pid_flush - recover memory used by stale /proc/@pid/x entries - * @proc_entry: directoy to prune. + * @proc_dentry: directoy to prune. * * Shrink the /proc directory that was used by the just killed thread. */ diff --git a/fs/seq_file.c b/fs/seq_file.c index 650c43ba86c4..38ef913767ff 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -51,7 +51,10 @@ EXPORT_SYMBOL(seq_open); /** * seq_read - ->read() method for sequential files. - * @file, @buf, @size, @ppos: see file_operations method + * @file: the file to read from + * @buf: the buffer to read to + * @size: the maximum number of bytes to read + * @ppos: the current position in the file * * Ready-made ->f_op->read() */ @@ -219,7 +222,9 @@ Eoverflow: /** * seq_lseek - ->llseek() method for sequential files. - * @file, @offset, @origin: see file_operations method + * @file: the file in question + * @offset: new position + * @origin: 0 for absolute, 1 for relative position * * Ready-made ->f_op->llseek() */ diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index da25aeb0e062..364208071e17 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -96,7 +96,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer /** * flush_read_buffer - push buffer to userspace. * @buffer: data buffer for file. - * @userbuf: user-passed buffer. + * @buf: user-passed buffer. * @count: number of bytes requested. * @ppos: file position. * @@ -164,7 +164,7 @@ out: /** * fill_write_buffer - copy buffer from userspace. * @buffer: data buffer for file. - * @userbuf: data from user. + * @buf: data from user. * @count: number of bytes in @userbuf. * * Allocate @buffer->page if it hasn't been already, then diff --git a/include/linux/fs.h b/include/linux/fs.h index 3f825b085c8d..4edba067a717 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1065,71 +1065,75 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * with a particular exported file system - particularly enabling nfsd and * the filesystem to co-operate when dealing with file handles. * - * export_operations contains two basic operation for dealing with file handles, - * decode_fh() and encode_fh(), and allows for some other operations to be defined - * which standard helper routines use to get specific information from the - * filesystem. + * export_operations contains two basic operation for dealing with file + * handles, decode_fh() and encode_fh(), and allows for some other + * operations to be defined which standard helper routines use to get + * specific information from the filesystem. * * nfsd encodes information use to determine which filesystem a filehandle - * applies to in the initial part of the file handle. The remainder, termed a - * file handle fragment, is controlled completely by the filesystem. - * The standard helper routines assume that this fragment will contain one or two - * sub-fragments, one which identifies the file, and one which may be used to - * identify the (a) directory containing the file. + * applies to in the initial part of the file handle. The remainder, termed + * a file handle fragment, is controlled completely by the filesystem. The + * standard helper routines assume that this fragment will contain one or + * two sub-fragments, one which identifies the file, and one which may be + * used to identify the (a) directory containing the file. * * In some situations, nfsd needs to get a dentry which is connected into a - * specific part of the file tree. To allow for this, it passes the function - * acceptable() together with a @context which can be used to see if the dentry - * is acceptable. As there can be multiple dentrys for a given file, the filesystem - * should check each one for acceptability before looking for the next. As soon - * as an acceptable one is found, it should be returned. + * specific part of the file tree. To allow for this, it passes the + * function acceptable() together with a @context which can be used to see + * if the dentry is acceptable. As there can be multiple dentrys for a + * given file, the filesystem should check each one for acceptability before + * looking for the next. As soon as an acceptable one is found, it should + * be returned. * * decode_fh: - * @decode_fh is given a &struct super_block (@sb), a file handle fragment (@fh, @fh_len) - * and an acceptability testing function (@acceptable, @context). It should return - * a &struct dentry which refers to the same file that the file handle fragment refers - * to, and which passes the acceptability test. If it cannot, it should return - * a %NULL pointer if the file was found but no acceptable &dentries were available, or - * a %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or %ENOMEM). + * @decode_fh is given a &struct super_block (@sb), a file handle fragment + * (@fh, @fh_len) and an acceptability testing function (@acceptable, + * @context). It should return a &struct dentry which refers to the same + * file that the file handle fragment refers to, and which passes the + * acceptability test. If it cannot, it should return a %NULL pointer if + * the file was found but no acceptable &dentries were available, or a + * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or + * %ENOMEM). * * encode_fh: - * @encode_fh should store in the file handle fragment @fh (using at most @max_len bytes) - * information that can be used by @decode_fh to recover the file refered to by the - * &struct dentry @de. If the @connectable flag is set, the encode_fh() should store - * sufficient information so that a good attempt can be made to find not only - * the file but also it's place in the filesystem. This typically means storing - * a reference to de->d_parent in the filehandle fragment. - * encode_fh() should return the number of bytes stored or a negative error code - * such as %-ENOSPC + * @encode_fh should store in the file handle fragment @fh (using at most + * @max_len bytes) information that can be used by @decode_fh to recover the + * file refered to by the &struct dentry @de. If the @connectable flag is + * set, the encode_fh() should store sufficient information so that a good + * attempt can be made to find not only the file but also it's place in the + * filesystem. This typically means storing a reference to de->d_parent in + * the filehandle fragment. encode_fh() should return the number of bytes + * stored or a negative error code such as %-ENOSPC * * get_name: - * @get_name should find a name for the given @child in the given @parent directory. - * The name should be stored in the @name (with the understanding that it is already - * pointing to a a %NAME_MAX+1 sized buffer. get_name() should return %0 on success, - * a negative error code or error. - * @get_name will be called without @parent->i_sem held. + * @get_name should find a name for the given @child in the given @parent + * directory. The name should be stored in the @name (with the + * understanding that it is already pointing to a a %NAME_MAX+1 sized + * buffer. get_name() should return %0 on success, a negative error code + * or error. @get_name will be called without @parent->i_sem held. * * get_parent: - * @get_parent should find the parent directory for the given @child which is also - * a directory. In the event that it cannot be found, or storage space cannot be - * allocated, a %ERR_PTR should be returned. + * @get_parent should find the parent directory for the given @child which + * is also a directory. In the event that it cannot be found, or storage + * space cannot be allocated, a %ERR_PTR should be returned. * * get_dentry: - * Given a &super_block (@sb) and a pointer to a file-system specific inode identifier, - * possibly an inode number, (@inump) get_dentry() should find the identified inode and - * return a dentry for that inode. - * Any suitable dentry can be returned including, if necessary, a new dentry created - * with d_alloc_root. The caller can then find any other extant dentrys by following the - * d_alias links. If a new dentry was created using d_alloc_root, DCACHE_NFSD_DISCONNECTED - * should be set, and the dentry should be d_rehash()ed. + * Given a &super_block (@sb) and a pointer to a file-system specific inode + * identifier, possibly an inode number, (@inump) get_dentry() should find + * the identified inode and return a dentry for that inode. Any suitable + * dentry can be returned including, if necessary, a new dentry created with + * d_alloc_root. The caller can then find any other extant dentrys by + * following the d_alias links. If a new dentry was created using + * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry + * should be d_rehash()ed. * - * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code can be returned. - * The @inump will be whatever was passed to nfsd_find_fh_dentry() in either the - * @obj or @parent parameters. + * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code + * can be returned. The @inump will be whatever was passed to + * nfsd_find_fh_dentry() in either the @obj or @parent parameters. * * Locking rules: - * get_parent is called with child->d_inode->i_sem down - * get_name is not (which is possibly inconsistent) + * get_parent is called with child->d_inode->i_sem down + * get_name is not (which is possibly inconsistent) */ struct export_operations { diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c77d745cbd3f..cc04f5cd2286 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -167,13 +167,14 @@ struct skb_shared_info { * @h: Transport layer header * @nh: Network layer header * @mac: Link layer header - * @dst: FIXME: Describe this field + * @dst: destination entry + * @sp: the security path, used for xfrm * @cb: Control buffer. Free for use by every layer. Put private vars here * @len: Length of actual data * @data_len: Data length * @mac_len: Length of link layer header * @csum: Checksum - * @__unused: Dead field, may be reused + * @local_df: allow local fragmentation * @cloned: Head may be cloned (check refcnt to be sure) * @nohdr: Payload reference only, must not modify header * @pkt_type: Packet class diff --git a/include/net/sock.h b/include/net/sock.h index 5bc180adfb14..cc4c9190b7fd 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -161,6 +161,7 @@ struct sock_common { * @sk_sndmsg_page: cached page for sendmsg * @sk_sndmsg_off: cached offset for sendmsg * @sk_send_head: front of stuff to transmit + * @sk_security: used by security modules * @sk_write_pending: a write to stream socket waits to start * @sk_state_change: callback to indicate change in the state of the sock * @sk_data_ready: callback to indicate there is data to be processed diff --git a/kernel/sched.c b/kernel/sched.c index 5dadcc6df7dd..0dc3158667a2 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -2906,6 +2906,7 @@ static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, * @q: the waitqueue * @mode: which threads * @nr_exclusive: how many wake-one or wake-many threads to wake up + * @key: is directly passed to the wakeup function */ void fastcall __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, void *key) @@ -2928,7 +2929,7 @@ void fastcall __wake_up_locked(wait_queue_head_t *q, unsigned int mode) } /** - * __wake_up - sync- wake up threads blocked on a waitqueue. + * __wake_up_sync - wake up threads blocked on a waitqueue. * @q: the waitqueue * @mode: which threads * @nr_exclusive: how many wake-one or wake-many threads to wake up diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 79dbd93bd697..701d12c63068 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1991,6 +1991,8 @@ int proc_dointvec_userhz_jiffies(ctl_table *table, int write, struct file *filp, * @filp: the file structure * @buffer: the user buffer * @lenp: the size of the user buffer + * @ppos: file position + * @ppos: the current position in the file * * Reads/writes up to table->maxlen/sizeof(unsigned int) integer * values from/to the user buffer, treated as an ASCII string. diff --git a/lib/kobject.c b/lib/kobject.c index 5df8441c44e7..94048826624c 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -216,13 +216,12 @@ int kobject_register(struct kobject * kobj) /** * kobject_set_name - Set the name of an object * @kobj: object. - * @name: name. + * @fmt: format string used to build the name * * If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated * string that @kobj->k_name points to. Otherwise, use the static * @kobj->name array. */ - int kobject_set_name(struct kobject * kobj, const char * fmt, ...) { int error = 0; diff --git a/mm/filemap.c b/mm/filemap.c index c085af2332d8..d5fdae2eb183 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -169,9 +169,10 @@ static int sync_page(void *word) /** * filemap_fdatawrite_range - start writeback against all of a mapping's * dirty pages that lie within the byte offsets - * @mapping: address space structure to write - * @start: offset in bytes where the range starts - * @end : offset in bytes where the range ends + * @mapping: address space structure to write + * @start: offset in bytes where the range starts + * @end: offset in bytes where the range ends + * @sync_mode: enable synchronous operation * * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as * opposed to a regular memory * cleansing writeback. The difference between @@ -535,8 +536,8 @@ EXPORT_SYMBOL(find_trylock_page); /** * find_lock_page - locate, pin and lock a pagecache page * - * @mapping - the address_space to search - * @offset - the page index + * @mapping: the address_space to search + * @offset: the page index * * Locates the desired pagecache page, locks it, increments its reference * count and returns its address. @@ -575,9 +576,9 @@ EXPORT_SYMBOL(find_lock_page); /** * find_or_create_page - locate or add a pagecache page * - * @mapping - the page's address_space - * @index - the page's index into the mapping - * @gfp_mask - page allocation mode + * @mapping: the page's address_space + * @index: the page's index into the mapping + * @gfp_mask: page allocation mode * * Locates a page in the pagecache. If the page is not present, a new page * is allocated using @gfp_mask and is added to the pagecache and to the VM's diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 6ddd6a29c73b..613b99a55917 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -255,7 +255,7 @@ static void balance_dirty_pages(struct address_space *mapping) /** * balance_dirty_pages_ratelimited - balance dirty memory state - * @mapping - address_space which was dirtied + * @mapping: address_space which was dirtied * * Processes which are dirtying memory should call in here once for each page * which was newly dirtied. The function will periodically check the system's @@ -562,8 +562,8 @@ int do_writepages(struct address_space *mapping, struct writeback_control *wbc) /** * write_one_page - write out a single page and optionally wait on I/O * - * @page - the page to write - * @wait - if true, wait on writeout + * @page: the page to write + * @wait: if true, wait on writeout * * The page must be locked by the caller and will be unlocked upon return. * diff --git a/mm/truncate.c b/mm/truncate.c index c9a63f0b69a2..60c8764bfac2 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -242,7 +242,7 @@ EXPORT_SYMBOL(invalidate_inode_pages); /** * invalidate_inode_pages2_range - remove range of pages from an address_space - * @mapping - the address_space + * @mapping: the address_space * @start: the page offset 'from' which to invalidate * @end: the page offset 'to' which to invalidate (inclusive) * @@ -322,7 +322,7 @@ EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range); /** * invalidate_inode_pages2 - remove all pages from an address_space - * @mapping - the address_space + * @mapping: the address_space * * Any pages which are found to be mapped into pagetables are unmapped prior to * invalidation. diff --git a/net/core/datagram.c b/net/core/datagram.c index 27c5cd942820..fcee054b6f75 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -203,7 +203,7 @@ void skb_free_datagram(struct sock *sk, struct sk_buff *skb) * skb_copy_datagram_iovec - Copy a datagram to an iovec. * @skb: buffer to copy * @offset: offset in the buffer to start copying from - * @iovec: io vector to copy to + * @to: io vector to copy to * @len: amount of data to copy from buffer to iovec * * Note: the iovec is modified during the copy. @@ -379,7 +379,7 @@ fault: * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. * @skb: skbuff * @hlen: hardware length - * @iovec: io vector + * @iov: io vector * * Caller _must_ check that skb will fit to this iovec. * -- cgit v1.2.3 From 66f3131f547ef3cc864810974e0757617e60a837 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:24:46 -0600 Subject: [PATCH] JFS: reduce number of synchronous transactions Use an inline pxd list rather than an xad list in the xadlock. When the number of extents being modified can fit with the xadlock, a transaction can be committed asynchronously. Using a list of pxd's instead of xad's allows us to fit 4 extents, rather than 2. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/jfs_txnmgr.c | 63 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 23 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index f40301d93f74..98e16d93e146 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -1712,7 +1712,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, struct maplock *maplock; struct xdlistlock *xadlock; struct pxd_lock *pxdlock; - pxd_t *pxd; + pxd_t *page_pxd; int next, lwm, hwm; ip = tlck->ip; @@ -1722,7 +1722,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, lrd->log.redopage.type = cpu_to_le16(LOG_XTREE); lrd->log.redopage.l2linesize = cpu_to_le16(L2XTSLOTSIZE); - pxd = &lrd->log.redopage.pxd; + page_pxd = &lrd->log.redopage.pxd; if (tlck->type & tlckBTROOT) { lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT); @@ -1752,9 +1752,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * applying the after-image to the meta-data page. */ lrd->type = cpu_to_le16(LOG_REDOPAGE); -// *pxd = mp->cm_pxd; - PXDaddress(pxd, mp->index); - PXDlength(pxd, +// *page_pxd = mp->cm_pxd; + PXDaddress(page_pxd, mp->index); + PXDlength(page_pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck)); @@ -1776,25 +1776,31 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, tlck->flag |= tlckUPDATEMAP; xadlock->flag = mlckALLOCXADLIST; xadlock->count = next - lwm; - if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) { + if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) { int i; + pxd_t *pxd; /* * Lazy commit may allow xtree to be modified before * txUpdateMap runs. Copy xad into linelock to * preserve correct data. + * + * We can fit twice as may pxd's as xads in the lock */ - xadlock->xdlist = &xtlck->pxdlock; - memcpy(xadlock->xdlist, &p->xad[lwm], - sizeof(xad_t) * xadlock->count); - - for (i = 0; i < xadlock->count; i++) + xadlock->flag = mlckALLOCPXDLIST; + pxd = xadlock->xdlist = &xtlck->pxdlock; + for (i = 0; i < xadlock->count; i++) { + PXDaddress(pxd, addressXAD(&p->xad[lwm + i])); + PXDlength(pxd, lengthXAD(&p->xad[lwm + i])); p->xad[lwm + i].flag &= ~(XAD_NEW | XAD_EXTENDED); + pxd++; + } } else { /* * xdlist will point to into inode's xtree, ensure * that transaction is not committed lazily. */ + xadlock->flag = mlckALLOCXADLIST; xadlock->xdlist = &p->xad[lwm]; tblk->xflag &= ~COMMIT_LAZY; } @@ -1836,8 +1842,8 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, if (tblk->xflag & COMMIT_TRUNCATE) { /* write NOREDOPAGE for the page */ lrd->type = cpu_to_le16(LOG_NOREDOPAGE); - PXDaddress(pxd, mp->index); - PXDlength(pxd, + PXDaddress(page_pxd, mp->index); + PXDlength(page_pxd, mp->logical_size >> tblk->sb-> s_blocksize_bits); lrd->backchain = @@ -1872,22 +1878,32 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * deleted page itself; */ tlck->flag |= tlckUPDATEMAP; - xadlock->flag = mlckFREEXADLIST; xadlock->count = hwm - XTENTRYSTART + 1; - if ((xadlock->count <= 2) && (tblk->xflag & COMMIT_LAZY)) { + if ((xadlock->count <= 4) && (tblk->xflag & COMMIT_LAZY)) { + int i; + pxd_t *pxd; /* * Lazy commit may allow xtree to be modified before * txUpdateMap runs. Copy xad into linelock to * preserve correct data. + * + * We can fit twice as may pxd's as xads in the lock */ - xadlock->xdlist = &xtlck->pxdlock; - memcpy(xadlock->xdlist, &p->xad[XTENTRYSTART], - sizeof(xad_t) * xadlock->count); + xadlock->flag = mlckFREEPXDLIST; + pxd = xadlock->xdlist = &xtlck->pxdlock; + for (i = 0; i < xadlock->count; i++) { + PXDaddress(pxd, + addressXAD(&p->xad[XTENTRYSTART + i])); + PXDlength(pxd, + lengthXAD(&p->xad[XTENTRYSTART + i])); + pxd++; + } } else { /* * xdlist will point to into inode's xtree, ensure * that transaction is not committed lazily. */ + xadlock->flag = mlckFREEXADLIST; xadlock->xdlist = &p->xad[XTENTRYSTART]; tblk->xflag &= ~COMMIT_LAZY; } @@ -1918,7 +1934,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * header ? */ if (tlck->type & tlckTRUNCATE) { - pxd_t tpxd; /* truncated extent of xad */ + pxd_t pxd; /* truncated extent of xad */ int twm; /* @@ -1947,8 +1963,9 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * applying the after-image to the meta-data page. */ lrd->type = cpu_to_le16(LOG_REDOPAGE); - PXDaddress(pxd, mp->index); - PXDlength(pxd, mp->logical_size >> tblk->sb->s_blocksize_bits); + PXDaddress(page_pxd, mp->index); + PXDlength(page_pxd, + mp->logical_size >> tblk->sb->s_blocksize_bits); lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck)); /* @@ -1966,7 +1983,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, lrd->log.updatemap.type = cpu_to_le16(LOG_FREEPXD); lrd->log.updatemap.nxd = cpu_to_le16(1); lrd->log.updatemap.pxd = pxdlock->pxd; - tpxd = pxdlock->pxd; /* save to format maplock */ + pxd = pxdlock->pxd; /* save to format maplock */ lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL)); } @@ -2035,7 +2052,7 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, pxdlock = (struct pxd_lock *) xadlock; pxdlock->flag = mlckFREEPXD; pxdlock->count = 1; - pxdlock->pxd = tpxd; + pxdlock->pxd = pxd; jfs_info("xtLog: truncate ip:0x%p mp:0x%p count:%d " "hwm:%d", ip, mp, pxdlock->count, hwm); -- cgit v1.2.3 From d2e83707edbe6a2520591141421d26a87414a1b9 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:24:51 -0600 Subject: [PATCH] JFS: Simplify creation of new iag JFS was creating a new IAG (inode aggregate group) in one address space, and afterwards, accessing it from another. This could lead to complications when cache pages contain more than one page of jfs metadata. This patch causes the IAG to be initialized in the same address space that it is subsequently accessed with. This also elimitates an I/O, but IAG's aren't created too often. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/jfs_imap.c | 70 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 783831301625..6a0aa7e2cbef 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -2573,9 +2573,18 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) goto out; } - /* assign a buffer for the page */ - mp = get_metapage(ipimap, xaddr, PSIZE, 1); - if (!mp) { + /* + * start transaction of update of the inode map + * addressing structure pointing to the new iag page; + */ + tid = txBegin(sb, COMMIT_FORCE); + down(&JFS_IP(ipimap)->commit_sem); + + /* update the inode map addressing structure to point to it */ + if ((rc = + xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { + txEnd(tid); + up(&JFS_IP(ipimap)->commit_sem); /* Free the blocks allocated for the iag since it was * not successfully added to the inode map */ @@ -2584,6 +2593,29 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) /* release the inode map lock */ IWRITE_UNLOCK(ipimap); + goto out; + } + + /* update the inode map's inode to reflect the extension */ + ipimap->i_size += PSIZE; + inode_add_bytes(ipimap, PSIZE); + + /* assign a buffer for the page */ + mp = get_metapage(ipimap, blkno, PSIZE, 0); + if (!mp) { + /* + * This is very unlikely since we just created the + * extent, but let's try to handle it correctly + */ + xtTruncate(tid, ipimap, ipimap->i_size - PSIZE, + COMMIT_PWMAP); + + txAbort(tid, 0); + txEnd(tid); + + /* release the inode map lock */ + IWRITE_UNLOCK(ipimap); + rc = -EIO; goto out; } @@ -2605,40 +2637,10 @@ diNewIAG(struct inomap * imap, int *iagnop, int agno, struct metapage ** mpp) iagp->inosmap[i] = cpu_to_le32(ONES); /* - * Invalidate the page after writing and syncing it. - * After it's initialized, we access it in a different - * address space + * Write and sync the metapage */ - set_bit(META_discard, &mp->flag); flush_metapage(mp); - /* - * start tyransaction of update of the inode map - * addressing structure pointing to the new iag page; - */ - tid = txBegin(sb, COMMIT_FORCE); - down(&JFS_IP(ipimap)->commit_sem); - - /* update the inode map addressing structure to point to it */ - if ((rc = - xtInsert(tid, ipimap, 0, blkno, xlen, &xaddr, 0))) { - txEnd(tid); - up(&JFS_IP(ipimap)->commit_sem); - /* Free the blocks allocated for the iag since it was - * not successfully added to the inode map - */ - dbFree(ipimap, xaddr, (s64) xlen); - - /* release the inode map lock */ - IWRITE_UNLOCK(ipimap); - - goto out; - } - - /* update the inode map's inode to reflect the extension */ - ipimap->i_size += PSIZE; - inode_add_bytes(ipimap, PSIZE); - /* * txCommit(COMMIT_FORCE) will synchronously write address * index pages and inode after commit in careful update order -- cgit v1.2.3 From dc5798d9a7b656550533a5c0177dba17d4ef4990 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:24:57 -0600 Subject: [PATCH] JFS: Changes for larger page size JFS code has always assumed a page size of 4K. This patch fixes the non-pagecache uses of pages to deal with larger pages. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/jfs_dtree.c | 2 +- fs/jfs/jfs_logmgr.c | 62 +++++++++++++++++++++++++++++++---------------------- fs/jfs/jfs_logmgr.h | 3 ++- 3 files changed, 39 insertions(+), 28 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index e357890adfb2..453bace608d1 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -3181,7 +3181,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) d = (struct ldtentry *) & p->slot[stbl[i]]; if (((long) jfs_dirent + d->namlen + 1) > - (dirent_buf + PSIZE)) { + (dirent_buf + PAGE_SIZE)) { /* DBCS codepages could overrun dirent_buf */ index = i; overflow = 1; diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index b6a6869ebb4f..e0f867ddfd10 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1669,6 +1669,7 @@ int lmLogShutdown(struct jfs_log * log) lp->h.eor = lp->t.eor = cpu_to_le16(bp->l_eor); lbmWrite(log, log->bp, lbmWRITE | lbmRELEASE | lbmSYNC, 0); lbmIOWait(log->bp, lbmFREE); + log->bp = NULL; /* * synchronous update log superblock @@ -1819,20 +1820,34 @@ static int lbmLogInit(struct jfs_log * log) log->lbuf_free = NULL; - for (i = 0; i < LOGPAGES; i++) { - lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL); - if (lbuf == 0) - goto error; - lbuf->l_ldata = (char *) get_zeroed_page(GFP_KERNEL); - if (lbuf->l_ldata == 0) { - kfree(lbuf); + for (i = 0; i < LOGPAGES;) { + char *buffer; + uint offset; + struct page *page; + + buffer = (char *) get_zeroed_page(GFP_KERNEL); + if (buffer == NULL) goto error; + page = virt_to_page(buffer); + for (offset = 0; offset < PAGE_SIZE; offset += LOGPSIZE) { + lbuf = kmalloc(sizeof(struct lbuf), GFP_KERNEL); + if (lbuf == NULL) { + if (offset == 0) + free_page((unsigned long) buffer); + goto error; + } + if (offset) /* we already have one reference */ + get_page(page); + lbuf->l_offset = offset; + lbuf->l_ldata = buffer + offset; + lbuf->l_page = page; + lbuf->l_log = log; + init_waitqueue_head(&lbuf->l_ioevent); + + lbuf->l_freelist = log->lbuf_free; + log->lbuf_free = lbuf; + i++; } - lbuf->l_log = log; - init_waitqueue_head(&lbuf->l_ioevent); - - lbuf->l_freelist = log->lbuf_free; - log->lbuf_free = lbuf; } return (0); @@ -1857,12 +1872,10 @@ static void lbmLogShutdown(struct jfs_log * log) lbuf = log->lbuf_free; while (lbuf) { struct lbuf *next = lbuf->l_freelist; - free_page((unsigned long) lbuf->l_ldata); + __free_page(lbuf->l_page); kfree(lbuf); lbuf = next; } - - log->bp = NULL; } @@ -1974,9 +1987,9 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); bio->bi_bdev = log->bdev; - bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata); + bio->bi_io_vec[0].bv_page = bp->l_page; bio->bi_io_vec[0].bv_len = LOGPSIZE; - bio->bi_io_vec[0].bv_offset = 0; + bio->bi_io_vec[0].bv_offset = bp->l_offset; bio->bi_vcnt = 1; bio->bi_idx = 0; @@ -2115,9 +2128,9 @@ static void lbmStartIO(struct lbuf * bp) bio = bio_alloc(GFP_NOFS, 1); bio->bi_sector = bp->l_blkno << (log->l2bsize - 9); bio->bi_bdev = log->bdev; - bio->bi_io_vec[0].bv_page = virt_to_page(bp->l_ldata); + bio->bi_io_vec[0].bv_page = bp->l_page; bio->bi_io_vec[0].bv_len = LOGPSIZE; - bio->bi_io_vec[0].bv_offset = 0; + bio->bi_io_vec[0].bv_offset = bp->l_offset; bio->bi_vcnt = 1; bio->bi_idx = 0; @@ -2127,16 +2140,13 @@ static void lbmStartIO(struct lbuf * bp) bio->bi_private = bp; /* check if journaling to disk has been disabled */ - if (!log->no_integrity) { + if (log->no_integrity) { + bio->bi_size = 0; + lbmIODone(bio, 0, 0); + } else { submit_bio(WRITE_SYNC, bio); INCREMENT(lmStat.submitted); } - else { - bio->bi_size = 0; - lbmIODone(bio, 0, 0); /* 2nd argument appears to not be used => 0 - * 3rd argument appears to not be used => 0 - */ - } } diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h index 141ad74010c9..f67146684b7f 100644 --- a/fs/jfs/jfs_logmgr.h +++ b/fs/jfs/jfs_logmgr.h @@ -463,9 +463,10 @@ struct lbuf { s64 l_blkno; /* 8: log page block number */ caddr_t l_ldata; /* 4: data page */ + struct page *l_page; /* The page itself */ + uint l_offset; /* Offset of l_ldata within the page */ wait_queue_head_t l_ioevent; /* 4: i/o done event */ - struct page *l_page; /* The page itself */ }; /* Reuse l_freelist for redrive list */ -- cgit v1.2.3 From 7fab479bebb96b1b4888bdae9b42e1fa9c5d3f38 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:25:02 -0600 Subject: [PATCH] JFS: Support page sizes greater than 4K jfs has never worked on architecutures where the page size was not 4K. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/inode.c | 31 +- fs/jfs/jfs_dmap.c | 12 +- fs/jfs/jfs_imap.c | 14 +- fs/jfs/jfs_incore.h | 1 + fs/jfs/jfs_logmgr.c | 71 ++-- fs/jfs/jfs_logmgr.h | 5 +- fs/jfs/jfs_metapage.c | 908 +++++++++++++++++++++++++++++++++----------------- fs/jfs/jfs_metapage.h | 80 +++-- fs/jfs/jfs_mount.c | 5 - fs/jfs/jfs_txnmgr.c | 89 +++-- fs/jfs/jfs_umount.c | 16 +- fs/jfs/resize.c | 3 + fs/jfs/super.c | 33 +- 13 files changed, 806 insertions(+), 462 deletions(-) (limited to 'fs') diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 7bc906677b0d..6c04f5eda135 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -175,31 +175,22 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, { s64 lblock64 = lblock; int rc = 0; - int take_locks; xad_t xad; s64 xaddr; int xflag; s32 xlen; - /* - * If this is a special inode (imap, dmap) - * the lock should already be taken - */ - take_locks = (JFS_IP(ip)->fileset != AGGREGATE_I); - /* * Take appropriate lock on inode */ - if (take_locks) { - if (create) - IWRITE_LOCK(ip); - else - IREAD_LOCK(ip); - } + if (create) + IWRITE_LOCK(ip); + else + IREAD_LOCK(ip); if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && - (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0) - == 0) && xlen) { + (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) && + xlen) { if (xflag & XAD_NOTRECORDED) { if (!create) /* @@ -258,12 +249,10 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, /* * Release lock on inode */ - if (take_locks) { - if (create) - IWRITE_UNLOCK(ip); - else - IREAD_UNLOCK(ip); - } + if (create) + IWRITE_UNLOCK(ip); + else + IREAD_UNLOCK(ip); return rc; } diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index d86e467c6e42..69007fd546ef 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -471,6 +471,7 @@ dbUpdatePMap(struct inode *ipbmap, struct metapage *mp; struct jfs_log *log; int lsn, difft, diffp; + unsigned long flags; /* the blocks better be within the mapsize. */ if (blkno + nblocks > bmp->db_mapsize) { @@ -504,6 +505,7 @@ dbUpdatePMap(struct inode *ipbmap, 0); if (mp == NULL) return -EIO; + metapage_wait_for_io(mp); } dp = (struct dmap *) mp->data; @@ -578,34 +580,32 @@ dbUpdatePMap(struct inode *ipbmap, if (mp->lsn != 0) { /* inherit older/smaller lsn */ logdiff(diffp, mp->lsn, log); + LOGSYNC_LOCK(log, flags); if (difft < diffp) { mp->lsn = lsn; /* move bp after tblock in logsync list */ - LOGSYNC_LOCK(log); list_move(&mp->synclist, &tblk->synclist); - LOGSYNC_UNLOCK(log); } /* inherit younger/larger clsn */ - LOGSYNC_LOCK(log); logdiff(difft, tblk->clsn, log); logdiff(diffp, mp->clsn, log); if (difft > diffp) mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } else { mp->log = log; mp->lsn = lsn; /* insert bp after tblock in logsync list */ - LOGSYNC_LOCK(log); + LOGSYNC_LOCK(log, flags); log->count++; list_add(&mp->synclist, &tblk->synclist); mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 6a0aa7e2cbef..7acff2ce3c80 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -502,7 +502,7 @@ struct inode *diReadSpecial(struct super_block *sb, ino_t inum, int secondary) } - ip->i_mapping->a_ops = &jfs_aops; + ip->i_mapping->a_ops = &jfs_metapage_aops; mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); /* Allocations to metadata inodes should not affect quotas */ @@ -2791,6 +2791,7 @@ diUpdatePMap(struct inode *ipimap, u32 mask; struct jfs_log *log; int lsn, difft, diffp; + unsigned long flags; imap = JFS_IP(ipimap)->i_imap; /* get the iag number containing the inode */ @@ -2807,6 +2808,7 @@ diUpdatePMap(struct inode *ipimap, IREAD_UNLOCK(ipimap); if (rc) return (rc); + metapage_wait_for_io(mp); iagp = (struct iag *) mp->data; /* get the inode number and extent number of the inode within * the iag and the inode number within the extent. @@ -2870,30 +2872,28 @@ diUpdatePMap(struct inode *ipimap, /* inherit older/smaller lsn */ logdiff(difft, lsn, log); logdiff(diffp, mp->lsn, log); + LOGSYNC_LOCK(log, flags); if (difft < diffp) { mp->lsn = lsn; /* move mp after tblock in logsync list */ - LOGSYNC_LOCK(log); list_move(&mp->synclist, &tblk->synclist); - LOGSYNC_UNLOCK(log); } /* inherit younger/larger clsn */ - LOGSYNC_LOCK(log); assert(mp->clsn); logdiff(difft, tblk->clsn, log); logdiff(diffp, mp->clsn, log); if (difft > diffp) mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } else { mp->log = log; mp->lsn = lsn; /* insert mp after tblock in logsync list */ - LOGSYNC_LOCK(log); + LOGSYNC_LOCK(log, flags); log->count++; list_add(&mp->synclist, &tblk->synclist); mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } write_metapage(mp); return (0); diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index ebd77c1bed66..c0fd7b3eadc6 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h @@ -165,6 +165,7 @@ struct jfs_sb_info { /* Formerly in ipbmap */ struct bmap *bmap; /* incore bmap descriptor */ struct nls_table *nls_tab; /* current codepage */ + struct inode *direct_inode; /* metadata inode */ uint state; /* mount/recovery state */ unsigned long flag; /* mount time flags */ uint p_state; /* state prior to going no integrity */ diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index e0f867ddfd10..cfcdad3459dd 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -234,6 +234,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, int lsn; int diffp, difft; struct metapage *mp = NULL; + unsigned long flags; jfs_info("lmLog: log:0x%p tblk:0x%p, lrd:0x%p tlck:0x%p", log, tblk, lrd, tlck); @@ -254,7 +255,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, */ lsn = log->lsn; - LOGSYNC_LOCK(log); + LOGSYNC_LOCK(log, flags); /* * initialize page lsn if first log write of the page @@ -310,7 +311,7 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, } } - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); /* * write the log record @@ -334,7 +335,6 @@ int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, return lsn; } - /* * NAME: lmWriteRecord() * @@ -945,6 +945,15 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) struct lrd lrd; int lsn; struct logsyncblk *lp; + struct jfs_sb_info *sbi; + unsigned long flags; + + /* push dirty metapages out to disk */ + list_for_each_entry(sbi, &log->sb_list, log_list) { + filemap_flush(sbi->ipbmap->i_mapping); + filemap_flush(sbi->ipimap->i_mapping); + filemap_flush(sbi->direct_inode->i_mapping); + } /* * forward syncpt @@ -954,10 +963,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) */ if (log->sync == log->syncpt) { - LOGSYNC_LOCK(log); - /* ToDo: push dirty metapages out to disk */ -// bmLogSync(log); - + LOGSYNC_LOCK(log, flags); if (list_empty(&log->synclist)) log->sync = log->lsn; else { @@ -965,7 +971,7 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) struct logsyncblk, synclist); log->sync = lp->lsn; } - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } @@ -974,27 +980,6 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) * reset syncpt = sync */ if (log->sync != log->syncpt) { - struct jfs_sb_info *sbi; - - /* - * We need to make sure all of the "written" metapages - * actually make it to disk - */ - list_for_each_entry(sbi, &log->sb_list, log_list) { - if (sbi->flag & JFS_NOINTEGRITY) - continue; - filemap_fdatawrite(sbi->ipbmap->i_mapping); - filemap_fdatawrite(sbi->ipimap->i_mapping); - filemap_fdatawrite(sbi->sb->s_bdev->bd_inode->i_mapping); - } - list_for_each_entry(sbi, &log->sb_list, log_list) { - if (sbi->flag & JFS_NOINTEGRITY) - continue; - filemap_fdatawait(sbi->ipbmap->i_mapping); - filemap_fdatawait(sbi->ipimap->i_mapping); - filemap_fdatawait(sbi->sb->s_bdev->bd_inode->i_mapping); - } - lrd.logtid = 0; lrd.backchain = 0; lrd.type = cpu_to_le16(LOG_SYNCPT); @@ -1547,6 +1532,7 @@ void jfs_flush_journal(struct jfs_log *log, int wait) { int i; struct tblock *target = NULL; + struct jfs_sb_info *sbi; /* jfs_write_inode may call us during read-only mount */ if (!log) @@ -1608,12 +1594,18 @@ void jfs_flush_journal(struct jfs_log *log, int wait) if (wait < 2) return; + list_for_each_entry(sbi, &log->sb_list, log_list) { + filemap_fdatawrite(sbi->ipbmap->i_mapping); + filemap_fdatawrite(sbi->ipimap->i_mapping); + filemap_fdatawrite(sbi->direct_inode->i_mapping); + } + /* * If there was recent activity, we may need to wait * for the lazycommit thread to catch up */ if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) { - for (i = 0; i < 800; i++) { /* Too much? */ + for (i = 0; i < 200; i++) { /* Too much? */ msleep(250); if (list_empty(&log->cqueue) && list_empty(&log->synclist)) @@ -1621,7 +1613,24 @@ void jfs_flush_journal(struct jfs_log *log, int wait) } } assert(list_empty(&log->cqueue)); - assert(list_empty(&log->synclist)); + if (!list_empty(&log->synclist)) { + struct logsyncblk *lp; + + list_for_each_entry(lp, &log->synclist, synclist) { + if (lp->xflag & COMMIT_PAGE) { + struct metapage *mp = (struct metapage *)lp; + dump_mem("orphan metapage", lp, + sizeof(struct metapage)); + dump_mem("page", mp->page, sizeof(struct page)); + } + else + dump_mem("orphan tblock", lp, + sizeof(struct tblock)); + } +// current->state = TASK_INTERRUPTIBLE; +// schedule(); + } + //assert(list_empty(&log->synclist)); clear_bit(log_FLUSH, &log->flag); } diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h index f67146684b7f..f4c121098d4f 100644 --- a/fs/jfs/jfs_logmgr.h +++ b/fs/jfs/jfs_logmgr.h @@ -490,8 +490,9 @@ struct logsyncblk { */ #define LOGSYNC_LOCK_INIT(log) spin_lock_init(&(log)->synclock) -#define LOGSYNC_LOCK(log) spin_lock(&(log)->synclock) -#define LOGSYNC_UNLOCK(log) spin_unlock(&(log)->synclock) +#define LOGSYNC_LOCK(log, flags) spin_lock_irqsave(&(log)->synclock, flags) +#define LOGSYNC_UNLOCK(log, flags) \ + spin_unlock_irqrestore(&(log)->synclock, flags) /* compute the difference in bytes of lsn from sync point */ #define logdiff(diff, lsn, log)\ diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 4c0a3ac75c08..41bf078dce05 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -1,5 +1,5 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2003 + * Copyright (C) International Business Machines Corp., 2000-2005 * Portions Copyright (C) Christoph Hellwig, 2001-2002 * * This program is free software; you can redistribute it and/or modify @@ -18,10 +18,11 @@ */ #include +#include +#include #include #include #include -#include #include "jfs_incore.h" #include "jfs_superblock.h" #include "jfs_filsys.h" @@ -29,8 +30,6 @@ #include "jfs_txnmgr.h" #include "jfs_debug.h" -static DEFINE_SPINLOCK(meta_lock); - #ifdef CONFIG_JFS_STATISTICS static struct { uint pagealloc; /* # of page allocations */ @@ -39,22 +38,8 @@ static struct { } mpStat; #endif - -#define HASH_BITS 10 /* This makes hash_table 1 4K page */ -#define HASH_SIZE (1 << HASH_BITS) -static struct metapage **hash_table = NULL; -static unsigned long hash_order; - - -static inline int metapage_locked(struct metapage *mp) -{ - return test_bit(META_locked, &mp->flag); -} - -static inline int trylock_metapage(struct metapage *mp) -{ - return test_and_set_bit(META_locked, &mp->flag); -} +#define metapage_locked(mp) test_bit(META_locked, &(mp)->flag) +#define trylock_metapage(mp) test_and_set_bit(META_locked, &(mp)->flag) static inline void unlock_metapage(struct metapage *mp) { @@ -62,26 +47,26 @@ static inline void unlock_metapage(struct metapage *mp) wake_up(&mp->wait); } -static void __lock_metapage(struct metapage *mp) +static inline void __lock_metapage(struct metapage *mp) { DECLARE_WAITQUEUE(wait, current); - INCREMENT(mpStat.lockwait); - add_wait_queue_exclusive(&mp->wait, &wait); do { set_current_state(TASK_UNINTERRUPTIBLE); if (metapage_locked(mp)) { - spin_unlock(&meta_lock); + unlock_page(mp->page); schedule(); - spin_lock(&meta_lock); + lock_page(mp->page); } } while (trylock_metapage(mp)); __set_current_state(TASK_RUNNING); remove_wait_queue(&mp->wait, &wait); } -/* needs meta_lock */ +/* + * Must have mp->page locked + */ static inline void lock_metapage(struct metapage *mp) { if (trylock_metapage(mp)) @@ -92,6 +77,110 @@ static inline void lock_metapage(struct metapage *mp) static kmem_cache_t *metapage_cache; static mempool_t *metapage_mempool; +#define MPS_PER_PAGE (PAGE_CACHE_SIZE >> L2PSIZE) + +#if MPS_PER_PAGE > 1 + +struct meta_anchor { + int mp_count; + atomic_t io_count; + struct metapage *mp[MPS_PER_PAGE]; +}; +#define mp_anchor(page) ((struct meta_anchor *)page->private) + +static inline struct metapage *page_to_mp(struct page *page, uint offset) +{ + if (!PagePrivate(page)) + return NULL; + return mp_anchor(page)->mp[offset >> L2PSIZE]; +} + +static inline int insert_metapage(struct page *page, struct metapage *mp) +{ + struct meta_anchor *a; + int index; + int l2mp_blocks; /* log2 blocks per metapage */ + + if (PagePrivate(page)) + a = mp_anchor(page); + else { + a = kmalloc(sizeof(struct meta_anchor), GFP_NOFS); + if (!a) + return -ENOMEM; + memset(a, 0, sizeof(struct meta_anchor)); + page->private = (unsigned long)a; + SetPagePrivate(page); + kmap(page); + } + + if (mp) { + l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits; + index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1); + a->mp_count++; + a->mp[index] = mp; + } + + return 0; +} + +static inline void remove_metapage(struct page *page, struct metapage *mp) +{ + struct meta_anchor *a = mp_anchor(page); + int l2mp_blocks = L2PSIZE - page->mapping->host->i_blkbits; + int index; + + index = (mp->index >> l2mp_blocks) & (MPS_PER_PAGE - 1); + + BUG_ON(a->mp[index] != mp); + + a->mp[index] = NULL; + if (--a->mp_count == 0) { + kfree(a); + page->private = 0; + ClearPagePrivate(page); + kunmap(page); + } +} + +static inline void inc_io(struct page *page) +{ + atomic_inc(&mp_anchor(page)->io_count); +} + +static inline void dec_io(struct page *page, void (*handler) (struct page *)) +{ + if (atomic_dec_and_test(&mp_anchor(page)->io_count)) + handler(page); +} + +#else +static inline struct metapage *page_to_mp(struct page *page, uint offset) +{ + return PagePrivate(page) ? (struct metapage *)page->private : NULL; +} + +static inline int insert_metapage(struct page *page, struct metapage *mp) +{ + if (mp) { + page->private = (unsigned long)mp; + SetPagePrivate(page); + kmap(page); + } + return 0; +} + +static inline void remove_metapage(struct page *page, struct metapage *mp) +{ + page->private = 0; + ClearPagePrivate(page); + kunmap(page); +} + +#define inc_io(page) do {} while(0) +#define dec_io(page, handler) handler(page) + +#endif + static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags) { struct metapage *mp = (struct metapage *)foo; @@ -139,16 +228,6 @@ int __init metapage_init(void) kmem_cache_destroy(metapage_cache); return -ENOMEM; } - /* - * Now the hash list - */ - for (hash_order = 0; - ((PAGE_SIZE << hash_order) / sizeof(void *)) < HASH_SIZE; - hash_order++); - hash_table = - (struct metapage **) __get_free_pages(GFP_KERNEL, hash_order); - assert(hash_table); - memset(hash_table, 0, PAGE_SIZE << hash_order); return 0; } @@ -159,73 +238,388 @@ void metapage_exit(void) kmem_cache_destroy(metapage_cache); } +static inline void drop_metapage(struct page *page, struct metapage *mp) +{ + if (mp->count || mp->nohomeok || test_bit(META_dirty, &mp->flag) || + test_bit(META_io, &mp->flag)) + return; + remove_metapage(page, mp); + INCREMENT(mpStat.pagefree); + free_metapage(mp); +} + /* - * Basically same hash as in pagemap.h, but using our hash table + * Metapage address space operations */ -static struct metapage **meta_hash(struct address_space *mapping, - unsigned long index) + +static sector_t metapage_get_blocks(struct inode *inode, sector_t lblock, + unsigned int *len) { -#define i (((unsigned long)mapping)/ \ - (sizeof(struct inode) & ~(sizeof(struct inode) -1 ))) -#define s(x) ((x) + ((x) >> HASH_BITS)) - return hash_table + (s(i + index) & (HASH_SIZE - 1)); -#undef i -#undef s + int rc = 0; + int xflag; + s64 xaddr; + sector_t file_blocks = (inode->i_size + inode->i_blksize - 1) >> + inode->i_blkbits; + + if (lblock >= file_blocks) + return 0; + if (lblock + *len > file_blocks) + *len = file_blocks - lblock; + + if (inode->i_ino) { + rc = xtLookup(inode, (s64)lblock, *len, &xflag, &xaddr, len, 0); + if ((rc == 0) && *len) + lblock = (sector_t)xaddr; + else + lblock = 0; + } /* else no mapping */ + + return lblock; } -static struct metapage *search_hash(struct metapage ** hash_ptr, - struct address_space *mapping, - unsigned long index) +static void last_read_complete(struct page *page) { - struct metapage *ptr; + if (!PageError(page)) + SetPageUptodate(page); + unlock_page(page); +} + +static int metapage_read_end_io(struct bio *bio, unsigned int bytes_done, + int err) +{ + struct page *page = bio->bi_private; + + if (bio->bi_size) + return 1; - for (ptr = *hash_ptr; ptr; ptr = ptr->hash_next) { - if ((ptr->mapping == mapping) && (ptr->index == index)) - return ptr; + if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) { + printk(KERN_ERR "metapage_read_end_io: I/O error\n"); + SetPageError(page); } - return NULL; + dec_io(page, last_read_complete); + bio_put(bio); + + return 0; } -static void add_to_hash(struct metapage * mp, struct metapage ** hash_ptr) +static void remove_from_logsync(struct metapage *mp) { - if (*hash_ptr) - (*hash_ptr)->hash_prev = mp; + struct jfs_log *log = mp->log; + unsigned long flags; +/* + * This can race. Recheck that log hasn't been set to null, and after + * acquiring logsync lock, recheck lsn + */ + if (!log) + return; + + LOGSYNC_LOCK(log, flags); + if (mp->lsn) { + mp->log = NULL; + mp->lsn = 0; + mp->clsn = 0; + log->count--; + list_del(&mp->synclist); + } + LOGSYNC_UNLOCK(log, flags); +} - mp->hash_prev = NULL; - mp->hash_next = *hash_ptr; - *hash_ptr = mp; +static void last_write_complete(struct page *page) +{ + struct metapage *mp; + unsigned int offset; + + for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) { + mp = page_to_mp(page, offset); + if (mp && test_bit(META_io, &mp->flag)) { + if (mp->lsn) + remove_from_logsync(mp); + clear_bit(META_io, &mp->flag); + } + /* + * I'd like to call drop_metapage here, but I don't think it's + * safe unless I have the page locked + */ + } + end_page_writeback(page); } -static void remove_from_hash(struct metapage * mp, struct metapage ** hash_ptr) +static int metapage_write_end_io(struct bio *bio, unsigned int bytes_done, + int err) { - if (mp->hash_prev) - mp->hash_prev->hash_next = mp->hash_next; - else { - assert(*hash_ptr == mp); - *hash_ptr = mp->hash_next; + struct page *page = bio->bi_private; + + BUG_ON(!PagePrivate(page)); + + if (bio->bi_size) + return 1; + + if (! test_bit(BIO_UPTODATE, &bio->bi_flags)) { + printk(KERN_ERR "metapage_write_end_io: I/O error\n"); + SetPageError(page); + } + dec_io(page, last_write_complete); + bio_put(bio); + return 0; +} + +static int metapage_writepage(struct page *page, struct writeback_control *wbc) +{ + struct bio *bio = NULL; + unsigned int block_offset; /* block offset of mp within page */ + struct inode *inode = page->mapping->host; + unsigned int blocks_per_mp = JFS_SBI(inode->i_sb)->nbperpage; + unsigned int len; + unsigned int xlen; + struct metapage *mp; + int redirty = 0; + sector_t lblock; + sector_t pblock; + sector_t next_block = 0; + sector_t page_start; + unsigned long bio_bytes = 0; + unsigned long bio_offset = 0; + unsigned int offset; + + page_start = (sector_t)page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + BUG_ON(!PageLocked(page)); + BUG_ON(PageWriteback(page)); + + for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) { + mp = page_to_mp(page, offset); + + if (!mp || !test_bit(META_dirty, &mp->flag)) + continue; + + if (mp->nohomeok && !test_bit(META_forcewrite, &mp->flag)) { + redirty = 1; + continue; + } + + clear_bit(META_dirty, &mp->flag); + block_offset = offset >> inode->i_blkbits; + lblock = page_start + block_offset; + if (bio) { + if (xlen && lblock == next_block) { + /* Contiguous, in memory & on disk */ + len = min(xlen, blocks_per_mp); + xlen -= len; + bio_bytes += len << inode->i_blkbits; + set_bit(META_io, &mp->flag); + continue; + } + /* Not contiguous */ + if (bio_add_page(bio, page, bio_bytes, bio_offset) < + bio_bytes) + goto add_failed; + /* + * Increment counter before submitting i/o to keep + * count from hitting zero before we're through + */ + inc_io(page); + if (!bio->bi_size) + goto dump_bio; + submit_bio(WRITE, bio); + bio = NULL; + } else { + set_page_writeback(page); + inc_io(page); + } + xlen = (PAGE_CACHE_SIZE - offset) >> inode->i_blkbits; + pblock = metapage_get_blocks(inode, lblock, &xlen); + if (!pblock) { + /* Need better error handling */ + printk(KERN_ERR "JFS: metapage_get_blocks failed\n"); + dec_io(page, last_write_complete); + continue; + } + set_bit(META_io, &mp->flag); + len = min(xlen, (uint) JFS_SBI(inode->i_sb)->nbperpage); + + bio = bio_alloc(GFP_NOFS, 1); + bio->bi_bdev = inode->i_sb->s_bdev; + bio->bi_sector = pblock << (inode->i_blkbits - 9); + bio->bi_end_io = metapage_write_end_io; + bio->bi_private = page; + + /* Don't call bio_add_page yet, we may add to this vec */ + bio_offset = offset; + bio_bytes = len << inode->i_blkbits; + + xlen -= len; + next_block = lblock + len; + } + if (bio) { + if (bio_add_page(bio, page, bio_bytes, bio_offset) < bio_bytes) + goto add_failed; + if (!bio->bi_size) + goto dump_bio; + + submit_bio(WRITE, bio); + } + if (redirty) + redirty_page_for_writepage(wbc, page); + + unlock_page(page); + + return 0; +add_failed: + /* We should never reach here, since we're only adding one vec */ + printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n"); + goto skip; +dump_bio: + dump_mem("bio", bio, sizeof(*bio)); +skip: + bio_put(bio); + unlock_page(page); + dec_io(page, last_write_complete); + + return -EIO; +} + +static int metapage_readpage(struct file *fp, struct page *page) +{ + struct inode *inode = page->mapping->host; + struct bio *bio = NULL; + unsigned int block_offset; + unsigned int blocks_per_page = PAGE_CACHE_SIZE >> inode->i_blkbits; + sector_t page_start; /* address of page in fs blocks */ + sector_t pblock; + unsigned int xlen; + unsigned int len; + unsigned int offset; + + BUG_ON(!PageLocked(page)); + page_start = (sector_t)page->index << + (PAGE_CACHE_SHIFT - inode->i_blkbits); + + block_offset = 0; + while (block_offset < blocks_per_page) { + xlen = blocks_per_page - block_offset; + pblock = metapage_get_blocks(inode, page_start + block_offset, + &xlen); + if (pblock) { + if (!PagePrivate(page)) + insert_metapage(page, NULL); + inc_io(page); + if (bio) + submit_bio(READ, bio); + + bio = bio_alloc(GFP_NOFS, 1); + bio->bi_bdev = inode->i_sb->s_bdev; + bio->bi_sector = pblock << (inode->i_blkbits - 9); + bio->bi_end_io = metapage_read_end_io; + bio->bi_private = page; + len = xlen << inode->i_blkbits; + offset = block_offset << inode->i_blkbits; + if (bio_add_page(bio, page, len, offset) < len) + goto add_failed; + block_offset += xlen; + } else + block_offset++; } + if (bio) + submit_bio(READ, bio); + else + unlock_page(page); + + return 0; - if (mp->hash_next) - mp->hash_next->hash_prev = mp->hash_prev; +add_failed: + printk(KERN_ERR "JFS: bio_add_page failed unexpectedly\n"); + bio_put(bio); + dec_io(page, last_read_complete); + return -EIO; } +static int metapage_releasepage(struct page *page, int gfp_mask) +{ + struct metapage *mp; + int busy = 0; + unsigned int offset; + + for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) { + mp = page_to_mp(page, offset); + + if (!mp) + continue; + + jfs_info("metapage_releasepage: mp = 0x%p", mp); + if (mp->count || mp->nohomeok) { + jfs_info("count = %ld, nohomeok = %d", mp->count, + mp->nohomeok); + busy = 1; + continue; + } + wait_on_page_writeback(page); + //WARN_ON(test_bit(META_dirty, &mp->flag)); + if (test_bit(META_dirty, &mp->flag)) { + dump_mem("dirty mp in metapage_releasepage", mp, + sizeof(struct metapage)); + dump_mem("page", page, sizeof(struct page)); + dump_stack(); + } + WARN_ON(mp->lsn); + if (mp->lsn) + remove_from_logsync(mp); + remove_metapage(page, mp); + INCREMENT(mpStat.pagefree); + free_metapage(mp); + } + if (busy) + return -1; + + return 0; +} + +static int metapage_invalidatepage(struct page *page, unsigned long offset) +{ + BUG_ON(offset); + + if (PageWriteback(page)) + return 0; + + return metapage_releasepage(page, 0); +} + +struct address_space_operations jfs_metapage_aops = { + .readpage = metapage_readpage, + .writepage = metapage_writepage, + .sync_page = block_sync_page, + .releasepage = metapage_releasepage, + .invalidatepage = metapage_invalidatepage, + .set_page_dirty = __set_page_dirty_nobuffers, +}; + struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, unsigned int size, int absolute, unsigned long new) { - struct metapage **hash_ptr; int l2BlocksPerPage; int l2bsize; struct address_space *mapping; - struct metapage *mp; + struct metapage *mp = NULL; + struct page *page; unsigned long page_index; unsigned long page_offset; - jfs_info("__get_metapage: inode = 0x%p, lblock = 0x%lx", inode, lblock); - + jfs_info("__get_metapage: ino = %ld, lblock = 0x%lx, abs=%d", + inode->i_ino, lblock, absolute); + + l2bsize = inode->i_blkbits; + l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; + page_index = lblock >> l2BlocksPerPage; + page_offset = (lblock - (page_index << l2BlocksPerPage)) << l2bsize; + if ((page_offset + size) > PAGE_CACHE_SIZE) { + jfs_err("MetaData crosses page boundary!!"); + jfs_err("lblock = %lx, size = %d", lblock, size); + dump_stack(); + return NULL; + } if (absolute) - mapping = inode->i_sb->s_bdev->bd_inode->i_mapping; + mapping = JFS_SBI(inode->i_sb)->direct_inode->i_mapping; else { /* * If an nfs client tries to read an inode that is larger @@ -237,312 +631,212 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, mapping = inode->i_mapping; } - hash_ptr = meta_hash(mapping, lblock); -again: - spin_lock(&meta_lock); - mp = search_hash(hash_ptr, mapping, lblock); + if (new && (PSIZE == PAGE_CACHE_SIZE)) { + page = grab_cache_page(mapping, page_index); + if (!page) { + jfs_err("grab_cache_page failed!"); + return NULL; + } + SetPageUptodate(page); + } else { + page = read_cache_page(mapping, page_index, + (filler_t *)mapping->a_ops->readpage, NULL); + if (IS_ERR(page)) { + jfs_err("read_cache_page failed!"); + return NULL; + } + lock_page(page); + } + + mp = page_to_mp(page, page_offset); if (mp) { - page_found: - if (test_bit(META_stale, &mp->flag)) { - spin_unlock(&meta_lock); - msleep(1); - goto again; + if (mp->logical_size != size) { + jfs_error(inode->i_sb, + "__get_metapage: mp->logical_size != size"); + jfs_err("logical_size = %d, size = %d", + mp->logical_size, size); + dump_stack(); + goto unlock; } mp->count++; lock_metapage(mp); - spin_unlock(&meta_lock); if (test_bit(META_discard, &mp->flag)) { if (!new) { jfs_error(inode->i_sb, "__get_metapage: using a " "discarded metapage"); - release_metapage(mp); - return NULL; + discard_metapage(mp); + goto unlock; } clear_bit(META_discard, &mp->flag); } - jfs_info("__get_metapage: found 0x%p, in hash", mp); - if (mp->logical_size != size) { - jfs_error(inode->i_sb, - "__get_metapage: mp->logical_size != size"); - release_metapage(mp); - return NULL; - } } else { - l2bsize = inode->i_blkbits; - l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; - page_index = lblock >> l2BlocksPerPage; - page_offset = (lblock - (page_index << l2BlocksPerPage)) << - l2bsize; - if ((page_offset + size) > PAGE_CACHE_SIZE) { - spin_unlock(&meta_lock); - jfs_err("MetaData crosses page boundary!!"); - return NULL; - } - - /* - * Locks held on aggregate inode pages are usually - * not held long, and they are taken in critical code - * paths (committing dirty inodes, txCommit thread) - * - * Attempt to get metapage without blocking, tapping into - * reserves if necessary. - */ - mp = NULL; - if (JFS_IP(inode)->fileset == AGGREGATE_I) { - mp = alloc_metapage(GFP_ATOMIC); - if (!mp) { - /* - * mempool is supposed to protect us from - * failing here. We will try a blocking - * call, but a deadlock is possible here - */ - printk(KERN_WARNING - "__get_metapage: atomic call to mempool_alloc failed.\n"); - printk(KERN_WARNING - "Will attempt blocking call\n"); - } - } - if (!mp) { - struct metapage *mp2; - - spin_unlock(&meta_lock); - mp = alloc_metapage(GFP_NOFS); - spin_lock(&meta_lock); - - /* we dropped the meta_lock, we need to search the - * hash again. - */ - mp2 = search_hash(hash_ptr, mapping, lblock); - if (mp2) { - free_metapage(mp); - mp = mp2; - goto page_found; - } - } + INCREMENT(mpStat.pagealloc); + mp = alloc_metapage(GFP_NOFS); + mp->page = page; mp->flag = 0; - lock_metapage(mp); - if (absolute) - set_bit(META_absolute, &mp->flag); mp->xflag = COMMIT_PAGE; mp->count = 1; - atomic_set(&mp->nohomeok,0); - mp->mapping = mapping; - mp->index = lblock; - mp->page = NULL; + mp->nohomeok = 0; mp->logical_size = size; - add_to_hash(mp, hash_ptr); - spin_unlock(&meta_lock); - - if (new) { - jfs_info("__get_metapage: Calling grab_cache_page"); - mp->page = grab_cache_page(mapping, page_index); - if (!mp->page) { - jfs_err("grab_cache_page failed!"); - goto freeit; - } else { - INCREMENT(mpStat.pagealloc); - unlock_page(mp->page); - } - } else { - jfs_info("__get_metapage: Calling read_cache_page"); - mp->page = read_cache_page(mapping, lblock, - (filler_t *)mapping->a_ops->readpage, NULL); - if (IS_ERR(mp->page)) { - jfs_err("read_cache_page failed!"); - goto freeit; - } else - INCREMENT(mpStat.pagealloc); + mp->data = page_address(page) + page_offset; + mp->index = lblock; + if (unlikely(insert_metapage(page, mp))) { + free_metapage(mp); + goto unlock; } - mp->data = kmap(mp->page) + page_offset; + lock_metapage(mp); } - if (new) + if (new) { + jfs_info("zeroing mp = 0x%p", mp); memset(mp->data, 0, PSIZE); + } - jfs_info("__get_metapage: returning = 0x%p", mp); + unlock_page(page); + jfs_info("__get_metapage: returning = 0x%p data = 0x%p", mp, mp->data); return mp; -freeit: - spin_lock(&meta_lock); - remove_from_hash(mp, hash_ptr); - free_metapage(mp); - spin_unlock(&meta_lock); +unlock: + unlock_page(page); return NULL; } -void hold_metapage(struct metapage * mp, int force) +void grab_metapage(struct metapage * mp) { - spin_lock(&meta_lock); - + jfs_info("grab_metapage: mp = 0x%p", mp); + page_cache_get(mp->page); + lock_page(mp->page); mp->count++; - - if (force) { - ASSERT (!(test_bit(META_forced, &mp->flag))); - if (trylock_metapage(mp)) - set_bit(META_forced, &mp->flag); - } else - lock_metapage(mp); - - spin_unlock(&meta_lock); + lock_metapage(mp); + unlock_page(mp->page); } -static void __write_metapage(struct metapage * mp) +void force_metapage(struct metapage *mp) { - int l2bsize = mp->mapping->host->i_blkbits; - int l2BlocksPerPage = PAGE_CACHE_SHIFT - l2bsize; - unsigned long page_index; - unsigned long page_offset; - int rc; - - jfs_info("__write_metapage: mp = 0x%p", mp); - - page_index = mp->page->index; - page_offset = - (mp->index - (page_index << l2BlocksPerPage)) << l2bsize; + struct page *page = mp->page; + jfs_info("force_metapage: mp = 0x%p", mp); + set_bit(META_forcewrite, &mp->flag); + clear_bit(META_sync, &mp->flag); + page_cache_get(page); + lock_page(page); + set_page_dirty(page); + write_one_page(page, 1); + clear_bit(META_forcewrite, &mp->flag); + page_cache_release(page); +} +extern void hold_metapage(struct metapage *mp) +{ lock_page(mp->page); - rc = mp->mapping->a_ops->prepare_write(NULL, mp->page, page_offset, - page_offset + - mp->logical_size); - if (rc) { - jfs_err("prepare_write return %d!", rc); - ClearPageUptodate(mp->page); +} + +extern void put_metapage(struct metapage *mp) +{ + if (mp->count || mp->nohomeok) { + /* Someone else will release this */ unlock_page(mp->page); - clear_bit(META_dirty, &mp->flag); return; } - rc = mp->mapping->a_ops->commit_write(NULL, mp->page, page_offset, - page_offset + - mp->logical_size); - if (rc) { - jfs_err("commit_write returned %d", rc); - } - + page_cache_get(mp->page); + mp->count++; + lock_metapage(mp); unlock_page(mp->page); - clear_bit(META_dirty, &mp->flag); - - jfs_info("__write_metapage done"); -} - -static inline void sync_metapage(struct metapage *mp) -{ - struct page *page = mp->page; - - page_cache_get(page); - lock_page(page); - - /* we're done with this page - no need to check for errors */ - if (page_has_buffers(page)) - write_one_page(page, 1); - else - unlock_page(page); - page_cache_release(page); + release_metapage(mp); } void release_metapage(struct metapage * mp) { - struct jfs_log *log; - + struct page *page = mp->page; jfs_info("release_metapage: mp = 0x%p, flag = 0x%lx", mp, mp->flag); - spin_lock(&meta_lock); - if (test_bit(META_forced, &mp->flag)) { - clear_bit(META_forced, &mp->flag); - mp->count--; - spin_unlock(&meta_lock); - return; - } + BUG_ON(!page); + + lock_page(page); + unlock_metapage(mp); assert(mp->count); - if (--mp->count || atomic_read(&mp->nohomeok)) { - unlock_metapage(mp); - spin_unlock(&meta_lock); + if (--mp->count || mp->nohomeok) { + unlock_page(page); + page_cache_release(page); return; } - if (mp->page) { - set_bit(META_stale, &mp->flag); - spin_unlock(&meta_lock); - kunmap(mp->page); - mp->data = NULL; - if (test_bit(META_dirty, &mp->flag)) - __write_metapage(mp); + if (test_bit(META_dirty, &mp->flag)) { + set_page_dirty(page); if (test_bit(META_sync, &mp->flag)) { - sync_metapage(mp); clear_bit(META_sync, &mp->flag); + write_one_page(page, 1); + lock_page(page); /* write_one_page unlocks the page */ } + } else if (mp->lsn) /* discard_metapage doesn't remove it */ + remove_from_logsync(mp); - if (test_bit(META_discard, &mp->flag)) { - lock_page(mp->page); - block_invalidatepage(mp->page, 0); - unlock_page(mp->page); - } - - page_cache_release(mp->page); - mp->page = NULL; - INCREMENT(mpStat.pagefree); - spin_lock(&meta_lock); - } +#if MPS_PER_PAGE == 1 + /* + * If we know this is the only thing in the page, we can throw + * the page out of the page cache. If pages are larger, we + * don't want to do this. + */ - if (mp->lsn) { - /* - * Remove metapage from logsynclist. - */ - log = mp->log; - LOGSYNC_LOCK(log); - mp->log = NULL; - mp->lsn = 0; - mp->clsn = 0; - log->count--; - list_del(&mp->synclist); - LOGSYNC_UNLOCK(log); + /* Retest mp->count since we may have released page lock */ + if (test_bit(META_discard, &mp->flag) && !mp->count) { + clear_page_dirty(page); + ClearPageUptodate(page); +#ifdef _NOT_YET + if (page->mapping) { + /* Remove from page cache and page cache reference */ + remove_from_page_cache(page); + page_cache_release(page); + metapage_releasepage(page, 0); + } +#endif } - remove_from_hash(mp, meta_hash(mp->mapping, mp->index)); - spin_unlock(&meta_lock); - - free_metapage(mp); +#else + /* Try to keep metapages from using up too much memory */ + drop_metapage(page, mp); +#endif + unlock_page(page); + page_cache_release(page); } void __invalidate_metapages(struct inode *ip, s64 addr, int len) { - struct metapage **hash_ptr; - unsigned long lblock; + sector_t lblock; int l2BlocksPerPage = PAGE_CACHE_SHIFT - ip->i_blkbits; + int BlocksPerPage = 1 << l2BlocksPerPage; /* All callers are interested in block device's mapping */ - struct address_space *mapping = ip->i_sb->s_bdev->bd_inode->i_mapping; + struct address_space *mapping = + JFS_SBI(ip->i_sb)->direct_inode->i_mapping; struct metapage *mp; struct page *page; + unsigned int offset; /* - * First, mark metapages to discard. They will eventually be + * Mark metapages to discard. They will eventually be * released, but should not be written. */ - for (lblock = addr; lblock < addr + len; - lblock += 1 << l2BlocksPerPage) { - hash_ptr = meta_hash(mapping, lblock); -again: - spin_lock(&meta_lock); - mp = search_hash(hash_ptr, mapping, lblock); - if (mp) { - if (test_bit(META_stale, &mp->flag)) { - spin_unlock(&meta_lock); - msleep(1); - goto again; - } + for (lblock = addr & ~(BlocksPerPage - 1); lblock < addr + len; + lblock += BlocksPerPage) { + page = find_lock_page(mapping, lblock >> l2BlocksPerPage); + if (!page) + continue; + for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) { + mp = page_to_mp(page, offset); + if (!mp) + continue; + if (mp->index < addr) + continue; + if (mp->index >= addr + len) + break; clear_bit(META_dirty, &mp->flag); set_bit(META_discard, &mp->flag); - spin_unlock(&meta_lock); - } else { - spin_unlock(&meta_lock); - page = find_lock_page(mapping, lblock>>l2BlocksPerPage); - if (page) { - block_invalidatepage(page, 0); - unlock_page(page); - page_cache_release(page); - } + if (mp->lsn) + remove_from_logsync(mp); } + unlock_page(page); + page_cache_release(page); } } diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h index 0e58aba58c37..991e9fb84c75 100644 --- a/fs/jfs/jfs_metapage.h +++ b/fs/jfs/jfs_metapage.h @@ -33,38 +33,27 @@ struct metapage { unsigned long flag; /* See Below */ unsigned long count; /* Reference count */ void *data; /* Data pointer */ - - /* list management stuff */ - struct metapage *hash_prev; - struct metapage *hash_next; /* Also used for free list */ - - /* - * mapping & index become redundant, but we need these here to - * add the metapage to the hash before we have the real page - */ - struct address_space *mapping; - unsigned long index; + sector_t index; /* block address of page */ wait_queue_head_t wait; /* implementation */ struct page *page; - unsigned long logical_size; + unsigned int logical_size; /* Journal management */ int clsn; - atomic_t nohomeok; + int nohomeok; struct jfs_log *log; }; /* metapage flag */ #define META_locked 0 -#define META_absolute 1 -#define META_free 2 -#define META_dirty 3 -#define META_sync 4 -#define META_discard 5 -#define META_forced 6 -#define META_stale 7 +#define META_free 1 +#define META_dirty 2 +#define META_sync 3 +#define META_discard 4 +#define META_forcewrite 5 +#define META_io 6 #define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag) @@ -80,7 +69,16 @@ extern struct metapage *__get_metapage(struct inode *inode, __get_metapage(inode, lblock, size, absolute, TRUE) extern void release_metapage(struct metapage *); -extern void hold_metapage(struct metapage *, int); +extern void grab_metapage(struct metapage *); +extern void force_metapage(struct metapage *); + +/* + * hold_metapage and put_metapage are used in conjuction. The page lock + * is not dropped between the two, so no other threads can get or release + * the metapage + */ +extern void hold_metapage(struct metapage *); +extern void put_metapage(struct metapage *); static inline void write_metapage(struct metapage *mp) { @@ -101,6 +99,46 @@ static inline void discard_metapage(struct metapage *mp) release_metapage(mp); } +static inline void metapage_nohomeok(struct metapage *mp) +{ + struct page *page = mp->page; + lock_page(page); + if (!mp->nohomeok++) { + mark_metapage_dirty(mp); + page_cache_get(page); + wait_on_page_writeback(page); + } + unlock_page(page); +} + +/* + * This serializes access to mp->lsn when metapages are added to logsynclist + * without setting nohomeok. i.e. updating imap & dmap + */ +static inline void metapage_wait_for_io(struct metapage *mp) +{ + if (test_bit(META_io, &mp->flag)) + wait_on_page_writeback(mp->page); +} + +/* + * This is called when already holding the metapage + */ +static inline void _metapage_homeok(struct metapage *mp) +{ + if (!--mp->nohomeok) + page_cache_release(mp->page); +} + +static inline void metapage_homeok(struct metapage *mp) +{ + hold_metapage(mp); + _metapage_homeok(mp); + put_metapage(mp); +} + +extern struct address_space_operations jfs_metapage_aops; + /* * This routines invalidate all pages for an extent. */ diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index c535ffd638e8..032d111bc330 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -285,11 +285,6 @@ int jfs_mount_rw(struct super_block *sb, int remount) */ logMOUNT(sb); - /* - * Set page cache allocation policy - */ - mapping_set_gfp_mask(sb->s_bdev->bd_inode->i_mapping, GFP_NOFS); - return rc; } diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index 98e16d93e146..bbc9c1407b55 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -227,6 +227,7 @@ static lid_t txLockAlloc(void) static void txLockFree(lid_t lid) { + TxLock[lid].tid = 0; TxLock[lid].next = TxAnchor.freelock; TxAnchor.freelock = lid; TxAnchor.tlocksInUse--; @@ -633,8 +634,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, /* is page locked by the requester transaction ? */ tlck = lid_to_tlock(lid); - if ((xtid = tlck->tid) == tid) + if ((xtid = tlck->tid) == tid) { + TXN_UNLOCK(); goto grantLock; + } /* * is page locked by anonymous transaction/lock ? @@ -649,6 +652,7 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, */ if (xtid == 0) { tlck->tid = tid; + TXN_UNLOCK(); tblk = tid_to_tblock(tid); /* * The order of the tlocks in the transaction is important @@ -706,17 +710,18 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, */ tlck->tid = tid; + TXN_UNLOCK(); + /* mark tlock for meta-data page */ if (mp->xflag & COMMIT_PAGE) { tlck->flag = tlckPAGELOCK; /* mark the page dirty and nohomeok */ - mark_metapage_dirty(mp); - atomic_inc(&mp->nohomeok); + metapage_nohomeok(mp); jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p", - mp, atomic_read(&mp->nohomeok), tid, tlck); + mp, mp->nohomeok, tid, tlck); /* if anonymous transaction, and buffer is on the group * commit synclist, mark inode to show this. This will @@ -762,8 +767,10 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, if (tlck->next == 0) { /* This inode's first anonymous transaction */ jfs_ip->atltail = lid; + TXN_LOCK(); list_add_tail(&jfs_ip->anon_inode_list, &TxAnchor.anon_list); + TXN_UNLOCK(); } } @@ -821,8 +828,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, grantLock: tlck->type |= type; - TXN_UNLOCK(); - return tlck; /* @@ -841,11 +846,19 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp, BUG(); } INCREMENT(stattx.waitlock); /* statistics */ + TXN_UNLOCK(); release_metapage(mp); + TXN_LOCK(); + xtid = tlck->tid; /* reaquire after dropping TXN_LOCK */ jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d", tid, xtid, lid); - TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); + + /* Recheck everything since dropping TXN_LOCK */ + if (xtid && (tlck->mp == mp) && (mp->lid == lid)) + TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor); + else + TXN_UNLOCK(); jfs_info("txLock: awakened tid = %d, lid = %d", tid, lid); return NULL; @@ -906,6 +919,7 @@ static void txUnlock(struct tblock * tblk) struct metapage *mp; struct jfs_log *log; int difft, diffp; + unsigned long flags; jfs_info("txUnlock: tblk = 0x%p", tblk); log = JFS_SBI(tblk->sb)->log; @@ -925,19 +939,14 @@ static void txUnlock(struct tblock * tblk) assert(mp->xflag & COMMIT_PAGE); /* hold buffer - * - * It's possible that someone else has the metapage. - * The only things were changing are nohomeok, which - * is handled atomically, and clsn which is protected - * by the LOGSYNC_LOCK. */ - hold_metapage(mp, 1); + hold_metapage(mp); - assert(atomic_read(&mp->nohomeok) > 0); - atomic_dec(&mp->nohomeok); + assert(mp->nohomeok > 0); + _metapage_homeok(mp); /* inherit younger/larger clsn */ - LOGSYNC_LOCK(log); + LOGSYNC_LOCK(log, flags); if (mp->clsn) { logdiff(difft, tblk->clsn, log); logdiff(diffp, mp->clsn, log); @@ -945,16 +954,11 @@ static void txUnlock(struct tblock * tblk) mp->clsn = tblk->clsn; } else mp->clsn = tblk->clsn; - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); assert(!(tlck->flag & tlckFREEPAGE)); - if (tlck->flag & tlckWRITEPAGE) { - write_metapage(mp); - } else { - /* release page which has been forced */ - release_metapage(mp); - } + put_metapage(mp); } /* insert tlock, and linelock(s) of the tlock if any, @@ -981,10 +985,10 @@ static void txUnlock(struct tblock * tblk) * has been inserted in logsync list at txUpdateMap()) */ if (tblk->lsn) { - LOGSYNC_LOCK(log); + LOGSYNC_LOCK(log, flags); log->count--; list_del(&tblk->synclist); - LOGSYNC_UNLOCK(log); + LOGSYNC_UNLOCK(log, flags); } } @@ -1573,8 +1577,8 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd, * the last entry, so don't bother logging this */ mp->lid = 0; - hold_metapage(mp, 0); - atomic_dec(&mp->nohomeok); + grab_metapage(mp); + metapage_homeok(mp); discard_metapage(mp); tlck->mp = NULL; return 0; @@ -2270,7 +2274,8 @@ void txForce(struct tblock * tblk) tlck->flag &= ~tlckWRITEPAGE; /* do not release page to freelist */ - + force_metapage(mp); +#if 0 /* * The "right" thing to do here is to * synchronously write the metadata. @@ -2282,9 +2287,10 @@ void txForce(struct tblock * tblk) * we can get by with synchronously writing * the pages when they are released. */ - assert(atomic_read(&mp->nohomeok)); + assert(mp->nohomeok); set_bit(META_dirty, &mp->flag); set_bit(META_sync, &mp->flag); +#endif } } } @@ -2344,7 +2350,7 @@ static void txUpdateMap(struct tblock * tblk) */ mp = tlck->mp; ASSERT(mp->xflag & COMMIT_PAGE); - hold_metapage(mp, 0); + grab_metapage(mp); } /* @@ -2394,8 +2400,8 @@ static void txUpdateMap(struct tblock * tblk) ASSERT(mp->lid == lid); tlck->mp->lid = 0; } - assert(atomic_read(&mp->nohomeok) == 1); - atomic_dec(&mp->nohomeok); + assert(mp->nohomeok == 1); + metapage_homeok(mp); discard_metapage(mp); tlck->mp = NULL; } @@ -2861,24 +2867,9 @@ static void LogSyncRelease(struct metapage * mp) { struct jfs_log *log = mp->log; - assert(atomic_read(&mp->nohomeok)); + assert(mp->nohomeok); assert(log); - atomic_dec(&mp->nohomeok); - - if (atomic_read(&mp->nohomeok)) - return; - - hold_metapage(mp, 0); - - LOGSYNC_LOCK(log); - mp->log = NULL; - mp->lsn = 0; - mp->clsn = 0; - log->count--; - list_del_init(&mp->synclist); - LOGSYNC_UNLOCK(log); - - release_metapage(mp); + metapage_homeok(mp); } /* diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c index f31a9e3f3fec..5cf91785b541 100644 --- a/fs/jfs/jfs_umount.c +++ b/fs/jfs/jfs_umount.c @@ -49,7 +49,6 @@ */ int jfs_umount(struct super_block *sb) { - struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping; struct jfs_sb_info *sbi = JFS_SBI(sb); struct inode *ipbmap = sbi->ipbmap; struct inode *ipimap = sbi->ipimap; @@ -109,8 +108,8 @@ int jfs_umount(struct super_block *sb) * Make sure all metadata makes it to disk before we mark * the superblock as clean */ - filemap_fdatawrite(bdev_mapping); - filemap_fdatawait(bdev_mapping); + filemap_fdatawrite(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); /* * ensure all file system file pages are propagated to their @@ -123,9 +122,6 @@ int jfs_umount(struct super_block *sb) if (log) { /* log = NULL if read-only mount */ updateSuper(sb, FM_CLEAN); - /* Restore default gfp_mask for bdev */ - mapping_set_gfp_mask(bdev_mapping, GFP_USER); - /* * close log: * @@ -140,7 +136,6 @@ int jfs_umount(struct super_block *sb) int jfs_umount_rw(struct super_block *sb) { - struct address_space *bdev_mapping = sb->s_bdev->bd_inode->i_mapping; struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_log *log = sbi->log; @@ -166,13 +161,10 @@ int jfs_umount_rw(struct super_block *sb) * mark the superblock clean before everything is flushed to * disk. */ - filemap_fdatawrite(bdev_mapping); - filemap_fdatawait(bdev_mapping); + filemap_fdatawrite(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); updateSuper(sb, FM_CLEAN); - /* Restore default gfp_mask for bdev */ - mapping_set_gfp_mask(bdev_mapping, GFP_USER); - return lmLogClose(sb); } diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 2eb6869b6e72..c6dc254d3253 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c @@ -209,6 +209,9 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) */ txQuiesce(sb); + /* Reset size of direct inode */ + sbi->direct_inode->i_size = sb->s_bdev->bd_inode->i_size; + if (sbi->mntflag & JFS_INLINELOG) { /* * deactivate old inline log diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 5856866e24fc..0812005364a1 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -210,6 +210,10 @@ static void jfs_put_super(struct super_block *sb) unload_nls(sbi->nls_tab); sbi->nls_tab = NULL; + truncate_inode_pages(sbi->direct_inode->i_mapping, 0); + iput(sbi->direct_inode); + sbi->direct_inode = NULL; + kfree(sbi); } @@ -358,6 +362,12 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data) } if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { + /* + * Invalidate any previously read metadata. fsck may have + * changed the on-disk data since we mounted r/o + */ + truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0); + JFS_SBI(sb)->flag = flag; return jfs_mount_rw(sb, 1); } @@ -428,12 +438,26 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &jfs_super_operations; sb->s_export_op = &jfs_export_operations; + /* + * Initialize direct-mapping inode/address-space + */ + inode = new_inode(sb); + if (inode == NULL) + goto out_kfree; + inode->i_ino = 0; + inode->i_nlink = 1; + inode->i_size = sb->s_bdev->bd_inode->i_size; + inode->i_mapping->a_ops = &jfs_metapage_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); + + sbi->direct_inode = inode; + rc = jfs_mount(sb); if (rc) { if (!silent) { jfs_err("jfs_mount failed w/return code = %d", rc); } - goto out_kfree; + goto out_mount_failed; } if (sb->s_flags & MS_RDONLY) sbi->log = NULL; @@ -482,6 +506,13 @@ out_no_rw: if (rc) { jfs_err("jfs_umount failed with return code %d", rc); } +out_mount_failed: + filemap_fdatawrite(sbi->direct_inode->i_mapping); + filemap_fdatawait(sbi->direct_inode->i_mapping); + truncate_inode_pages(sbi->direct_inode->i_mapping, 0); + make_bad_inode(sbi->direct_inode); + iput(sbi->direct_inode); + sbi->direct_inode = NULL; out_kfree: if (sbi->nls_tab) unload_nls(sbi->nls_tab); -- cgit v1.2.3 From 1c6278295d6482edaaaef5faa64b18f17b3319b7 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:25:08 -0600 Subject: [PATCH] JFS: Write journal sync points more often This patch adds jfs_syncpt, which calls lmLogSync to write sync points to the journal both in jfs_sync_fs and when sync barrier processing completes. lmLogSync accomplishes two things: 1) it pushes logged-but-dirty metadata pages to disk, and 2) it writes a sync record to the journal so that jfs_fsck doesn't need to replay more transactions than is necessary. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/jfs_logmgr.c | 17 ++++++++++++++--- fs/jfs/jfs_logmgr.h | 1 + fs/jfs/jfs_txnmgr.c | 14 +++++++++----- fs/jfs/super.c | 4 +++- 4 files changed, 27 insertions(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index cfcdad3459dd..dfa1200daa61 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -927,9 +927,8 @@ static void lmPostGC(struct lbuf * bp) * calculate new value of i_nextsync which determines when * this code is called again. * - * this is called only from lmLog(). - * - * PARAMETER: ip - pointer to logs inode. + * PARAMETERS: log - log structure + * nosyncwait - 1 if called asynchronously * * RETURN: 0 * @@ -1051,6 +1050,18 @@ static int lmLogSync(struct jfs_log * log, int nosyncwait) return lsn; } +/* + * NAME: jfs_syncpt + * + * FUNCTION: write log SYNCPT record for specified log + * + * PARAMETERS: log - log structure + */ +void jfs_syncpt(struct jfs_log *log) +{ LOG_LOCK(log); + lmLogSync(log, 1); + LOG_UNLOCK(log); +} /* * NAME: lmLogOpen() diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h index f4c121098d4f..51291fbc420c 100644 --- a/fs/jfs/jfs_logmgr.h +++ b/fs/jfs/jfs_logmgr.h @@ -508,5 +508,6 @@ extern int lmLogShutdown(struct jfs_log * log); extern int lmLogInit(struct jfs_log * log); extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize); extern void jfs_flush_journal(struct jfs_log * log, int wait); +extern void jfs_syncpt(struct jfs_log *log); #endif /* _H_JFS_LOGMGR */ diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c index bbc9c1407b55..e93d01aa12c4 100644 --- a/fs/jfs/jfs_txnmgr.c +++ b/fs/jfs/jfs_txnmgr.c @@ -567,9 +567,6 @@ void txEnd(tid_t tid) * synchronize with logsync barrier */ if (test_bit(log_SYNCBARRIER, &log->flag)) { - /* forward log syncpt */ - /* lmSync(log); */ - jfs_info("log barrier off: 0x%x", log->lsn); /* enable new transactions start */ @@ -577,15 +574,22 @@ void txEnd(tid_t tid) /* wakeup all waitors for logsync barrier */ TXN_WAKEUP(&log->syncwait); + + TXN_UNLOCK(); + + /* forward log syncpt */ + jfs_syncpt(log); + + goto wakeup; } } + TXN_UNLOCK(); +wakeup: /* * wakeup all waitors for a free tblock */ TXN_WAKEUP(&TxAnchor.freewait); - - TXN_UNLOCK(); } diff --git a/fs/jfs/super.c b/fs/jfs/super.c index 0812005364a1..5e774ed7fb64 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -558,8 +558,10 @@ static int jfs_sync_fs(struct super_block *sb, int wait) struct jfs_log *log = JFS_SBI(sb)->log; /* log == NULL indicates read-only mount */ - if (log) + if (log) { jfs_flush_journal(log, wait); + jfs_syncpt(log); + } return 0; } -- cgit v1.2.3 From 6628465e33ca694bd8fd5c3cf4eb7ff9177bc694 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Mon, 2 May 2005 12:25:13 -0600 Subject: [PATCH] JFS: Don't allocate extents that overlap existing extents Modify xtSearch so that it returns the next allocated block when the requested block is unmapped. This can be used to make sure we don't create a new extent that overlaps the next one. Signed-off-by: Dave Kleikamp Signed-off-by: Linus Torvalds --- fs/jfs/inode.c | 6 +++--- fs/jfs/jfs_dtree.c | 4 ++-- fs/jfs/jfs_xtree.c | 61 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 46 insertions(+), 25 deletions(-) (limited to 'fs') diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 6c04f5eda135..24a689179af2 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -178,7 +178,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, xad_t xad; s64 xaddr; int xflag; - s32 xlen; + s32 xlen = max_blocks; /* * Take appropriate lock on inode @@ -190,7 +190,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && (!xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, 0)) && - xlen) { + xaddr) { if (xflag & XAD_NOTRECORDED) { if (!create) /* @@ -229,7 +229,7 @@ jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks, #ifdef _JFS_4K if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) goto unlock; - rc = extAlloc(ip, max_blocks, lblock64, &xad, FALSE); + rc = extAlloc(ip, xlen, lblock64, &xad, FALSE); if (rc) goto unlock; diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 453bace608d1..ac41f72d6d50 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -212,7 +212,7 @@ static struct metapage *read_index_page(struct inode *inode, s64 blkno) s32 xlen; rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1); - if (rc || (xlen == 0)) + if (rc || (xaddr == 0)) return NULL; return read_metapage(inode, xaddr, PSIZE, 1); @@ -231,7 +231,7 @@ static struct metapage *get_index_page(struct inode *inode, s64 blkno) s32 xlen; rc = xtLookup(inode, blkno, 1, &xflag, &xaddr, &xlen, 1); - if (rc || (xlen == 0)) + if (rc || (xaddr == 0)) return NULL; return get_metapage(inode, xaddr, PSIZE, 1); diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index 11c58c54b818..2c1f311914a1 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -111,8 +111,8 @@ static struct { /* * forward references */ -static int xtSearch(struct inode *ip, - s64 xoff, int *cmpp, struct btstack * btstack, int flag); +static int xtSearch(struct inode *ip, s64 xoff, s64 *next, int *cmpp, + struct btstack * btstack, int flag); static int xtSplitUp(tid_t tid, struct inode *ip, @@ -159,11 +159,12 @@ int xtLookup(struct inode *ip, s64 lstart, xtpage_t *p; int index; xad_t *xad; - s64 size, xoff, xend; + s64 next, size, xoff, xend; int xlen; s64 xaddr; - *plen = 0; + *paddr = 0; + *plen = llen; if (!no_check) { /* is lookup offset beyond eof ? */ @@ -180,7 +181,7 @@ int xtLookup(struct inode *ip, s64 lstart, * search for the xad entry covering the logical extent */ //search: - if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) { + if ((rc = xtSearch(ip, lstart, &next, &cmp, &btstack, 0))) { jfs_err("xtLookup: xtSearch returned %d", rc); return rc; } @@ -198,8 +199,11 @@ int xtLookup(struct inode *ip, s64 lstart, * lstart is a page start address, * i.e., lstart cannot start in a hole; */ - if (cmp) + if (cmp) { + if (next) + *plen = min(next - lstart, llen); goto out; + } /* * lxd covered by xad @@ -284,7 +288,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, if (lstart >= size) return 0; - if ((rc = xtSearch(ip, lstart, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, lstart, NULL, &cmp, &btstack, 0))) return rc; /* @@ -488,6 +492,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, * parameters: * ip - file object; * xoff - extent offset; + * nextp - address of next extent (if any) for search miss * cmpp - comparison result: * btstack - traverse stack; * flag - search process flag (XT_INSERT); @@ -497,7 +502,7 @@ int xtLookupList(struct inode *ip, struct lxdlist * lxdlist, * *cmpp is set to result of comparison with the entry returned. * the page containing the entry is pinned at exit. */ -static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ +static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, int *cmpp, struct btstack * btstack, int flag) { struct jfs_inode_info *jfs_ip = JFS_IP(ip); @@ -511,6 +516,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ struct btframe *btsp; int nsplit = 0; /* number of pages to split */ s64 t64; + s64 next = 0; INCREMENT(xtStat.search); @@ -579,6 +585,7 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ * previous and this entry */ *cmpp = 1; + next = t64; goto out; } @@ -623,6 +630,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ /* update sequential access heuristics */ jfs_ip->btindex = index; + if (nextp) + *nextp = next; + INCREMENT(xtStat.fastSearch); return 0; } @@ -675,10 +685,11 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ return 0; } - /* search hit - internal page: * descend/search its child page */ + if (index < p->header.nextindex - 1) + next = offsetXAD(&p->xad[index + 1]); goto next; } @@ -694,6 +705,8 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ * base is the smallest index with key (Kj) greater than * search key (K) and may be zero or maxentry index. */ + if (base < p->header.nextindex) + next = offsetXAD(&p->xad[base]); /* * search miss - leaf page: * @@ -727,6 +740,9 @@ static int xtSearch(struct inode *ip, s64 xoff, /* offset of extent */ jfs_ip->btorder = BT_RANDOM; jfs_ip->btindex = base; + if (nextp) + *nextp = next; + return 0; } @@ -793,6 +809,7 @@ int xtInsert(tid_t tid, /* transaction id */ struct xtsplit split; /* split information */ xad_t *xad; int cmp; + s64 next; struct tlock *tlck; struct xtlock *xtlck; @@ -806,7 +823,7 @@ int xtInsert(tid_t tid, /* transaction id */ * n.b. xtSearch() may return index of maxentry of * the full page. */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -814,7 +831,7 @@ int xtInsert(tid_t tid, /* transaction id */ /* This test must follow XT_GETSEARCH since mp must be valid if * we branch to out: */ - if (cmp == 0) { + if ((cmp == 0) || (next && (xlen > next - xoff))) { rc = -EEXIST; goto out; } @@ -1626,7 +1643,7 @@ int xtExtend(tid_t tid, /* transaction id */ jfs_info("xtExtend: nxoff:0x%lx nxlen:0x%x", (ulong) xoff, xlen); /* there must exist extent to be extended */ - if ((rc = xtSearch(ip, xoff - 1, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff - 1, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -1794,7 +1811,7 @@ printf("xtTailgate: nxoff:0x%lx nxlen:0x%x nxaddr:0x%lx\n", */ /* there must exist extent to be tailgated */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -1977,7 +1994,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) nxlen = lengthXAD(nxad); nxaddr = addressXAD(nxad); - if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2291,7 +2308,7 @@ int xtUpdate(tid_t tid, struct inode *ip, xad_t * nxad) if (nextindex == le16_to_cpu(p->header.maxentry)) { XT_PUTPAGE(mp); - if ((rc = xtSearch(ip, nxoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, nxoff, NULL, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2438,6 +2455,7 @@ int xtAppend(tid_t tid, /* transaction id */ int nsplit, nblocks, xlen; struct pxdlist pxdlist; pxd_t *pxd; + s64 next; xaddr = *xaddrp; xlen = *xlenp; @@ -2452,7 +2470,7 @@ int xtAppend(tid_t tid, /* transaction id */ * n.b. xtSearch() may return index of maxentry of * the full page. */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, XT_INSERT))) + if ((rc = xtSearch(ip, xoff, &next, &cmp, &btstack, XT_INSERT))) return rc; /* retrieve search result */ @@ -2462,6 +2480,9 @@ int xtAppend(tid_t tid, /* transaction id */ rc = -EEXIST; goto out; } + + if (next) + xlen = min(xlen, (int)(next - xoff)); //insert: /* * insert entry for new extent @@ -2600,7 +2621,7 @@ int xtDelete(tid_t tid, struct inode *ip, s64 xoff, s32 xlen, int flag) /* * find the matching entry; xtSearch() pins the page */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) return rc; XT_GETSEARCH(ip, btstack.top, bn, mp, p, index); @@ -2852,7 +2873,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ */ if (xtype == DATAEXT) { /* search in leaf entry */ - rc = xtSearch(ip, xoff, &cmp, &btstack, 0); + rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0); if (rc) return rc; @@ -2958,7 +2979,7 @@ xtRelocate(tid_t tid, struct inode * ip, xad_t * oxad, /* old XAD */ } /* get back parent page */ - if ((rc = xtSearch(ip, xoff, &cmp, &btstack, 0))) + if ((rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0))) return rc; XT_GETSEARCH(ip, btstack.top, bn, pmp, pp, index); @@ -3991,7 +4012,7 @@ s64 xtTruncate_pmap(tid_t tid, struct inode *ip, s64 committed_size) if (committed_size) { xoff = (committed_size >> JFS_SBI(ip->i_sb)->l2bsize) - 1; - rc = xtSearch(ip, xoff, &cmp, &btstack, 0); + rc = xtSearch(ip, xoff, NULL, &cmp, &btstack, 0); if (rc) return rc; -- cgit v1.2.3 From 6b6bf51081a27e80334e7ebe2993ae1d046a3222 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Wed, 4 May 2005 09:11:49 -0500 Subject: JFS: Endian errors Thanks sparse! Signed-off-by: Dave Kleikamp --- fs/jfs/jfs_xtree.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c index 2c1f311914a1..31b34db4519e 100644 --- a/fs/jfs/jfs_xtree.c +++ b/fs/jfs/jfs_xtree.c @@ -1,5 +1,5 @@ /* - * Copyright (C) International Business Machines Corp., 2000-2004 + * Copyright (C) International Business Machines Corp., 2000-2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -688,7 +688,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, /* search hit - internal page: * descend/search its child page */ - if (index < p->header.nextindex - 1) + if (index < le16_to_cpu(p->header.nextindex)-1) next = offsetXAD(&p->xad[index + 1]); goto next; } @@ -705,7 +705,7 @@ static int xtSearch(struct inode *ip, s64 xoff, s64 *nextp, * base is the smallest index with key (Kj) greater than * search key (K) and may be zero or maxentry index. */ - if (base < p->header.nextindex) + if (base < le16_to_cpu(p->header.nextindex)) next = offsetXAD(&p->xad[base]); /* * search miss - leaf page: -- cgit v1.2.3 From 71bce256bf2e2aaddf54a2f4ac216329c74be3ad Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:23:27 -0700 Subject: [XFS] Move the XFS inode to the front of its hash list on a cache hit SGI Modid: xfs-linux:xfs-kern:21915a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_iget.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 3a0ba1dfd0e8..d3da00045f26 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -135,6 +135,40 @@ xfs_chash_free(xfs_mount_t *mp) mp->m_chash = NULL; } +/* + * Try to move an inode to the front of its hash list if possible + * (and if its not there already). Called right after obtaining + * the list version number and then dropping the read_lock on the + * hash list in question (which is done right after looking up the + * inode in question...). + */ +STATIC void +xfs_ihash_promote( + xfs_ihash_t *ih, + xfs_inode_t *ip, + ulong version) +{ + xfs_inode_t *iq; + + if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) { + if (likely(version == ih->ih_version)) { + /* remove from list */ + if ((iq = ip->i_next)) { + iq->i_prevp = ip->i_prevp; + } + *ip->i_prevp = iq; + + /* insert at list head */ + iq = ih->ih_next; + iq->i_prevp = &ip->i_next; + ip->i_next = iq; + ip->i_prevp = &ih->ih_next; + ih->ih_next = ip; + } + write_unlock(&ih->ih_lock); + } +} + /* * Look up an inode by number in the given file system. * The inode is looked up in the hash table for the file system @@ -229,7 +263,9 @@ again: XFS_STATS_INC(xs_ig_found); ip->i_flags &= ~XFS_IRECLAIMABLE; + version = ih->ih_version; read_unlock(&ih->ih_lock); + xfs_ihash_promote(ih, ip, version); XFS_MOUNT_ILOCK(mp); list_del_init(&ip->i_reclaim); @@ -259,8 +295,15 @@ again: inode_vp, vp); } + /* + * Inode cache hit: if ip is not at the front of + * its hash chain, move it there now. + * Do this with the lock held for update, but + * do statistics after releasing the lock. + */ + version = ih->ih_version; read_unlock(&ih->ih_lock); - + xfs_ihash_promote(ih, ip, version); XFS_STATS_INC(xs_ig_found); finish_inode: @@ -547,6 +590,7 @@ xfs_inode_incore(xfs_mount_t *mp, { xfs_ihash_t *ih; xfs_inode_t *ip; + ulong version; ih = XFS_IHASH(mp, ino); read_lock(&ih->ih_lock); @@ -554,11 +598,15 @@ xfs_inode_incore(xfs_mount_t *mp, if (ip->i_ino == ino) { /* * If we find it and tp matches, return it. + * Also move it to the front of the hash list + * if we find it and it is not already there. * Otherwise break from the loop and return * NULL. */ if (ip->i_transp == tp) { + version = ih->ih_version; read_unlock(&ih->ih_lock); + xfs_ihash_promote(ih, ip, version); return (ip); } break; @@ -685,6 +733,7 @@ xfs_iextract( iq->i_prevp = ip->i_prevp; } *ip->i_prevp = iq; + ih->ih_version++; write_unlock(&ih->ih_lock); /* -- cgit v1.2.3 From de20614b351e4d4d23af0a105baa8fd2d7cd4f26 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:24:13 -0700 Subject: [XFS] Block mount attempts for filesystems with version 1 directories. SGI Modid: xfs-linux:xfs-kern:21937a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_mount.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'fs') diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index b57423caef9b..2ec967d93e5a 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -300,6 +300,15 @@ xfs_mount_validate_sb( return XFS_ERROR(EFSCORRUPTED); } + /* + * Version 1 directory format has never worked on Linux. + */ + if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) { + cmn_err(CE_WARN, + "XFS: Attempted to mount file system using version 1 directory format"); + return XFS_ERROR(ENOSYS); + } + /* * Until this is fixed only page-sized or smaller data blocks work. */ -- cgit v1.2.3 From 31b084aef3f088962f56c100b31bb8479c5dd769 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:25:00 -0700 Subject: [XFS] Fix up uses of nlink_t incorrectly restricting us to 2^16 links for some platforms SGI Modid: xfs-linux:xfs-kern:22032a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_vnode.h | 2 +- fs/xfs/xfs_inode.c | 2 +- fs/xfs/xfs_inode.h | 6 +++--- fs/xfs/xfs_types.h | 1 + fs/xfs/xfs_utils.c | 2 +- fs/xfs/xfs_utils.h | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index da76c1f1e11c..7cff0f3e9bc3 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -409,7 +409,7 @@ typedef struct vattr { int va_mask; /* bit-mask of attributes present */ enum vtype va_type; /* vnode type (for create) */ mode_t va_mode; /* file access mode and type */ - nlink_t va_nlink; /* number of references to file */ + xfs_nlink_t va_nlink; /* number of references to file */ uid_t va_uid; /* owner user id */ gid_t va_gid; /* owner group id */ xfs_ino_t va_nodeid; /* file id */ diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 43c632ab86ad..bc8c8c7f9039 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1130,7 +1130,7 @@ xfs_ialloc( xfs_trans_t *tp, xfs_inode_t *pip, mode_t mode, - nlink_t nlink, + xfs_nlink_t nlink, xfs_dev_t rdev, cred_t *cr, xfs_prid_t prid, diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index a53b1ccf6070..37e1c316f3b6 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -495,9 +495,9 @@ int xfs_itobp(struct xfs_mount *, struct xfs_trans *, int xfs_iread(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, xfs_inode_t **, xfs_daddr_t); int xfs_iread_extents(struct xfs_trans *, xfs_inode_t *, int); -int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, nlink_t, - xfs_dev_t, struct cred *, xfs_prid_t, int, - struct xfs_buf **, boolean_t *, xfs_inode_t **); +int xfs_ialloc(struct xfs_trans *, xfs_inode_t *, mode_t, + xfs_nlink_t, xfs_dev_t, struct cred *, xfs_prid_t, + int, struct xfs_buf **, boolean_t *, xfs_inode_t **); void xfs_xlate_dinode_core(xfs_caddr_t, struct xfs_dinode_core *, int); uint xfs_ip2xflags(struct xfs_inode *); diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index 04609d27ea51..e4bf711e48ff 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h @@ -63,6 +63,7 @@ typedef __u64 xfs_ino_t; /* type */ typedef __s64 xfs_daddr_t; /* type */ typedef char * xfs_caddr_t; /* type */ typedef __u32 xfs_dev_t; +typedef __u32 xfs_nlink_t; /* __psint_t is the same size as a pointer */ #if (BITS_PER_LONG == 32) diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 816b945fa0ea..d1f8146a06ea 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c @@ -147,7 +147,7 @@ xfs_dir_ialloc( xfs_inode_t *dp, /* directory within whose allocate the inode. */ mode_t mode, - nlink_t nlink, + xfs_nlink_t nlink, xfs_dev_t rdev, cred_t *credp, prid_t prid, /* project id */ diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index e1ed6a588000..01d98b4b7af7 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h @@ -42,7 +42,7 @@ extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **); extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, xfs_inode_t **); extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); -extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, nlink_t, +extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, xfs_dev_t, cred_t *, prid_t, int, xfs_inode_t **, int *); extern int xfs_droplink (xfs_trans_t *, xfs_inode_t *); -- cgit v1.2.3 From 9effd8e62570c6e47b91734770e6122002c33ed5 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 5 May 2005 13:26:18 -0700 Subject: [XFS] Enable XFS_VNODE_TRACE SGI Modid: xfs-linux:xfs-kern:190725a Signed-off-by: Eric Sandeen Signed-off-by: Christoph Hellwig . --- fs/xfs/Makefile | 2 +- fs/xfs/linux-2.6/xfs_vnode.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 554e4a18c152..d3ff78354638 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -49,7 +49,7 @@ ifeq ($(CONFIG_XFS_TRACE),y) EXTRA_CFLAGS += -DXFS_LOG_TRACE EXTRA_CFLAGS += -DXFS_RW_TRACE EXTRA_CFLAGS += -DPAGEBUF_TRACE - # EXTRA_CFLAGS += -DXFS_VNODE_TRACE + EXTRA_CFLAGS += -DXFS_VNODE_TRACE endif obj-$(CONFIG_XFS_FS) += xfs.o diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 7cff0f3e9bc3..3b40c929544e 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -86,10 +86,11 @@ typedef struct vnode { vnumber_t v_number; /* in-core vnode number */ vn_bhv_head_t v_bh; /* behavior head */ spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ - struct inode v_inode; /* Linux inode */ #ifdef XFS_VNODE_TRACE struct ktrace *v_trace; /* trace header structure */ #endif + struct inode v_inode; /* Linux inode */ + /* inode MUST be last */ } vnode_t; #define v_fbhv v_bh.bh_first /* first behavior */ -- cgit v1.2.3 From 5fcbab355e1528545671a5221666ef640b8250c8 Mon Sep 17 00:00:00 2001 From: Dean Roehrich Date: Thu, 5 May 2005 13:27:19 -0700 Subject: [XFS] Add ATTR_NOLOCK for xfs_setattr to indicate that XFS_IOLOCK is held SGI Modid: xfs-linux:xfs-kern:190711a Signed-off-by: Dean Roehrich Signed-off-by: Christoph Hellwig . --- fs/xfs/linux-2.6/xfs_vnode.h | 1 + fs/xfs/xfs_vnodeops.c | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 3b40c929544e..4ee229301241 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -626,6 +626,7 @@ static inline int VN_BAD(struct vnode *vp) #define ATTR_DMI 0x08 /* invocation from a DMI function */ #define ATTR_LAZY 0x80 /* set/get attributes lazily */ #define ATTR_NONBLOCK 0x100 /* return EAGAIN if operation would block */ +#define ATTR_NOLOCK 0x200 /* Don't grab any conflicting locks */ /* * Flags to VOP_FSYNC and VOP_RECLAIM. diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 70092963ca9e..25a526629b12 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -305,7 +305,7 @@ xfs_setattr( int mandlock_before, mandlock_after; struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; int file_owner; - int need_iolock = (flags & ATTR_DMI) == 0; + int need_iolock = 1; vp = BHV_TO_VNODE(bdp); vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); @@ -384,6 +384,9 @@ xfs_setattr( */ tp = NULL; lock_flags = XFS_ILOCK_EXCL; + ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1); + if (flags & ATTR_NOLOCK) + need_iolock = 0; if (!(mask & XFS_AT_SIZE)) { if ((mask != (XFS_AT_CTIME|XFS_AT_ATIME|XFS_AT_MTIME)) || (mp->m_flags & XFS_MOUNT_WSYNC)) { @@ -4320,7 +4323,7 @@ xfs_free_file_space( int rt; xfs_fileoff_t startoffset_fsb; xfs_trans_t *tp; - int need_iolock = (attr_flags & ATTR_DMI) == 0; + int need_iolock = 1; vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address); mp = ip->i_mount; @@ -4348,8 +4351,12 @@ xfs_free_file_space( return(error); } + ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); + if (attr_flags & ATTR_NOLOCK) + need_iolock = 0; if (need_iolock) xfs_ilock(ip, XFS_IOLOCK_EXCL); + rounding = MAX((__uint8_t)(1 << mp->m_sb.sb_blocklog), (__uint8_t)NBPP); ilen = len + (offset & (rounding - 1)); -- cgit v1.2.3 From 1f443ad70d3afa6bc74019ade2d664eadd7d505a Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:28:29 -0700 Subject: [XFS] Allow initial XFS delayed allocation size to be increased beyond 64KB. SGI Modid: xfs-linux:xfs-kern:22261a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_mount.h | 6 ++--- fs/xfs/xfs_vfsops.c | 67 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 25 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 5fc6201dd8e2..1b968471ec8b 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -428,10 +428,10 @@ typedef struct xfs_mount { #define XFS_WRITEIO_LOG_LARGE 16 /* - * Max and min values for UIO and mount-option defined I/O sizes; - * min value can't be less than a page. Currently unused. + * Max and min values for mount-option defined I/O + * preallocation sizes. */ -#define XFS_MAX_IO_LOG 16 /* 64K */ +#define XFS_MAX_IO_LOG 30 /* 1G */ #define XFS_MIN_IO_LOG PAGE_SHIFT /* diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 00aae9c6a904..b53736650100 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c @@ -1649,6 +1649,7 @@ xfs_vget( #define MNTOPT_SWIDTH "swidth" /* data volume stripe width */ #define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */ #define MNTOPT_MTPT "mtpt" /* filesystem mount point */ +#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */ #define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */ #define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */ #define MNTOPT_NOLOGFLUSH "nologflush" /* don't hard flush on log writes */ @@ -1657,6 +1658,28 @@ xfs_vget( #define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */ #define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */ +STATIC unsigned long +suffix_strtoul(const char *cp, char **endp, unsigned int base) +{ + int last, shift_left_factor = 0; + char *value = (char *)cp; + + last = strlen(value) - 1; + if (value[last] == 'K' || value[last] == 'k') { + shift_left_factor = 10; + value[last] = '\0'; + } + if (value[last] == 'M' || value[last] == 'm') { + shift_left_factor = 20; + value[last] = '\0'; + } + if (value[last] == 'G' || value[last] == 'g') { + shift_left_factor = 30; + value[last] = '\0'; + } + + return simple_strtoul(cp, endp, base) << shift_left_factor; +} int xfs_parseargs( @@ -1688,60 +1711,60 @@ xfs_parseargs( if (!strcmp(this_char, MNTOPT_LOGBUFS)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_LOGBUFS); + this_char); return EINVAL; } args->logbufs = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { - int last, in_kilobytes = 0; - if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_LOGBSIZE); + this_char); return EINVAL; } - last = strlen(value) - 1; - if (value[last] == 'K' || value[last] == 'k') { - in_kilobytes = 1; - value[last] = '\0'; - } - args->logbufsize = simple_strtoul(value, &eov, 10); - if (in_kilobytes) - args->logbufsize <<= 10; + args->logbufsize = suffix_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_LOGDEV); + this_char); return EINVAL; } strncpy(args->logname, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_MTPT)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_MTPT); + this_char); return EINVAL; } strncpy(args->mtpt, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_RTDEV)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_RTDEV); + this_char); return EINVAL; } strncpy(args->rtname, value, MAXNAMELEN); } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_BIOSIZE); + this_char); return EINVAL; } iosize = simple_strtoul(value, &eov, 10); args->flags |= XFSMNT_IOSIZE; args->iosizelog = (uint8_t) iosize; + } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { + if (!value || !*value) { + printk("XFS: %s option requires an argument\n", + this_char); + return EINVAL; + } + iosize = suffix_strtoul(value, &eov, 10); + args->flags |= XFSMNT_IOSIZE; + args->iosizelog = ffs(iosize) - 1; } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - this_char); + this_char); return EINVAL; } args->flags |= XFSMNT_IHASHSIZE; @@ -1756,7 +1779,7 @@ xfs_parseargs( args->flags |= XFSMNT_INO64; #if !XFS_BIG_INUMS printk("XFS: %s option not allowed on this system\n", - MNTOPT_INO64); + this_char); return EINVAL; #endif } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { @@ -1766,14 +1789,14 @@ xfs_parseargs( } else if (!strcmp(this_char, MNTOPT_SUNIT)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_SUNIT); + this_char); return EINVAL; } dsunit = simple_strtoul(value, &eov, 10); } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { if (!value || !*value) { printk("XFS: %s option requires an argument\n", - MNTOPT_SWIDTH); + this_char); return EINVAL; } dswidth = simple_strtoul(value, &eov, 10); @@ -1781,7 +1804,7 @@ xfs_parseargs( args->flags &= ~XFSMNT_32BITINODES; #if !XFS_BIG_INUMS printk("XFS: %s option not allowed on this system\n", - MNTOPT_64BITINODE); + this_char); return EINVAL; #endif } else if (!strcmp(this_char, MNTOPT_NOUUID)) { @@ -1877,7 +1900,7 @@ xfs_showargs( seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize); if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) - seq_printf(m, "," MNTOPT_BIOSIZE "=%d", mp->m_writeio_log); + seq_printf(m, "," MNTOPT_ALLOCSIZE "=%d", 1<m_writeio_log); if (mp->m_logbufs > 0) seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs); -- cgit v1.2.3 From 764433b7f1cf5d7b5e27ceb4f5546042e1f4acc7 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 5 May 2005 13:29:17 -0700 Subject: [XFS] Fix up warnings SGI Modid: xfs-linux:xfs-kern:191411a Signed-off-by: Eric Sandeen Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_vnode.c | 4 ++-- fs/xfs/linux-2.6/xfs_vnode.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 849c61c74f3c..4b1b1bcdb6b3 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -424,13 +424,13 @@ vn_remove( * Vnode tracing code. */ void -vn_trace_entry(vnode_t *vp, char *func, inst_t *ra) +vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); } void -vn_trace_exit(vnode_t *vp, char *func, inst_t *ra) +vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra) { KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); } diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 4ee229301241..00466c3194ac 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -648,8 +648,8 @@ static inline int VN_BAD(struct vnode *vp) #define VNODE_KTRACE_REF 4 #define VNODE_KTRACE_RELE 5 -extern void vn_trace_entry(struct vnode *, char *, inst_t *); -extern void vn_trace_exit(struct vnode *, char *, inst_t *); +extern void vn_trace_entry(struct vnode *, const char *, inst_t *); +extern void vn_trace_exit(struct vnode *, const char *, inst_t *); extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); -- cgit v1.2.3 From abd0cf7aeaaf8a15d9777e65606b6076868b6186 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:30:13 -0700 Subject: [XFS] Resolve an issue with xfsbufd not getting along with swsusp. SGI Modid: xfs-linux:xfs-kern:22342a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_buf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 23e0eb67fc25..997963e53622 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -1746,13 +1746,15 @@ STATIC DECLARE_COMPLETION(pagebuf_daemon_done); STATIC struct task_struct *pagebuf_daemon_task; STATIC int pagebuf_daemon_active; STATIC int force_flush; - +STATIC int force_sleep; STATIC int pagebuf_daemon_wakeup( int priority, unsigned int mask) { + if (force_sleep) + return 0; force_flush = 1; barrier(); wake_up_process(pagebuf_daemon_task); @@ -1778,7 +1780,12 @@ pagebuf_daemon( INIT_LIST_HEAD(&tmp); do { - try_to_freeze(PF_FREEZE); + if (unlikely(current->flags & PF_FREEZE)) { + force_sleep = 1; + refrigerator(PF_FREEZE); + } else { + force_sleep = 0; + } set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((xfs_buf_timer_centisecs * HZ) / 100); -- cgit v1.2.3 From 3f243766660da3df4a75ea1892c310d6080646c8 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:30:34 -0700 Subject: [XFS] Disable the combination of XFS direct IO and AIO until the IO completion handling for unwritten extents can be moved out of interrupt context. SGI Modid: xfs-linux:xfs-kern:22343a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_file.c | 43 +++++++++++++++++++++++++++++++++++++++++-- fs/xfs/linux-2.6/xfs_lrw.c | 3 +++ 2 files changed, 44 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 9f057a4a5b06..d0d412afd261 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -515,10 +515,49 @@ open_exec_out: } #endif /* HAVE_FOP_OPEN_EXEC */ +/* + * Temporary workaround to the AIO direct IO write problem. + * This code can go and we can revert to do_sync_write once + * the writepage(s) rework is merged. + */ +STATIC ssize_t +linvfs_write( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *ppos) +{ + struct kiocb kiocb; + ssize_t ret; + + init_sync_kiocb(&kiocb, filp); + kiocb.ki_pos = *ppos; + ret = __linvfs_write(&kiocb, buf, 0, len, kiocb.ki_pos); + *ppos = kiocb.ki_pos; + return ret; +} +STATIC ssize_t +linvfs_write_invis( + struct file *filp, + const char __user *buf, + size_t len, + loff_t *ppos) +{ + struct kiocb kiocb; + ssize_t ret; + + init_sync_kiocb(&kiocb, filp); + kiocb.ki_pos = *ppos; + ret = __linvfs_write(&kiocb, buf, IO_INVIS, len, kiocb.ki_pos); + *ppos = kiocb.ki_pos; + return ret; +} + + struct file_operations linvfs_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .write = do_sync_write, + .write = linvfs_write, .readv = linvfs_readv, .writev = linvfs_writev, .aio_read = linvfs_aio_read, @@ -540,7 +579,7 @@ struct file_operations linvfs_file_operations = { struct file_operations linvfs_invis_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, - .write = do_sync_write, + .write = linvfs_write_invis, .readv = linvfs_readv_invis, .writev = linvfs_writev_invis, .aio_read = linvfs_aio_read_invis, diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index ff145fd0d1a4..aa9daaea6c34 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c @@ -683,6 +683,9 @@ xfs_write( (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? mp->m_rtdev_targp : mp->m_ddev_targp; + if (ioflags & IO_ISAIO) + return XFS_ERROR(-ENOSYS); + if ((pos & target->pbr_smask) || (count & target->pbr_smask)) return XFS_ERROR(-EINVAL); -- cgit v1.2.3 From 3ba0815a4b0709ef5e7b481067573d10806bbe2c Mon Sep 17 00:00:00 2001 From: Daniel Moore Date: Thu, 5 May 2005 13:31:34 -0700 Subject: [XFS] stop background sync from waiting for in-use inodes SGI Modid: xfs-linux:xfs-kern:191586a Signed-off-by: Daniel Moore Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_aops.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 76a84758073a..1e71a9633d8f 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -725,9 +725,12 @@ xfs_page_state_convert( __uint64_t end_offset; pgoff_t end_index, last_index, tlast; int len, err, i, cnt = 0, uptodate = 1; - int flags = startio ? 0 : BMAPI_TRYLOCK; + int flags; int page_dirty, delalloc = 0; + /* wait for other IO threads? */ + flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK; + /* Is this page beyond the end of the file? */ offset = i_size_read(inode); end_index = offset >> PAGE_CACHE_SHIFT; -- cgit v1.2.3 From 18e0a926ad7c5ab4ef05334230671c6975dac26b Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 5 May 2005 13:32:18 -0700 Subject: [XFS] remove noisy printk at vnode trace allocation SGI Modid: xfs-linux:xfs-kern:191625a Signed-off-by: Eric Sandeen Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_vnode.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index 4b1b1bcdb6b3..a832d165f24f 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c @@ -156,7 +156,6 @@ vn_initialize( #ifdef XFS_VNODE_TRACE vp->v_trace = ktrace_alloc(VNODE_TRACE_SIZE, KM_SLEEP); - printk("Allocated VNODE_TRACE at 0x%p\n", vp->v_trace); #endif /* XFS_VNODE_TRACE */ vn_trace_exit(vp, "vn_initialize", (inst_t *)__return_address); -- cgit v1.2.3 From 775bf6c99a4ebde13bdb8dfa528ed241483b49ef Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:33:01 -0700 Subject: [XFS] Do not do delalloc conversion on pages beyond EOF ever, not just sometimes SGI Modid: xfs-linux:xfs-kern:22376a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/linux-2.6/xfs_aops.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 1e71a9633d8f..1edd3b694332 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -726,7 +726,7 @@ xfs_page_state_convert( pgoff_t end_index, last_index, tlast; int len, err, i, cnt = 0, uptodate = 1; int flags; - int page_dirty, delalloc = 0; + int page_dirty; /* wait for other IO threads? */ flags = (startio && wbc->sync_mode != WB_SYNC_NONE) ? 0 : BMAPI_TRYLOCK; @@ -807,7 +807,6 @@ xfs_page_state_convert( */ } else if (buffer_delay(bh)) { if (!iomp) { - delalloc = 1; err = xfs_map_blocks(inode, offset, len, &iomap, BMAPI_ALLOCATE | flags); if (err) { @@ -882,10 +881,9 @@ xfs_page_state_convert( xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1); if (iomp) { - tlast = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> + offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> PAGE_CACHE_SHIFT; - if (delalloc && (tlast > last_index)) - tlast = last_index; + tlast = min_t(pgoff_t, offset, last_index); xfs_cluster_write(inode, page->index + 1, iomp, wbc, startio, unmapped, tlast); } -- cgit v1.2.3 From 24e17b5fb99d4d1b47fe0847a3a801e36d431ff6 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:33:20 -0700 Subject: [XFS] Use the right offset when ensuring a delayed allocate conversion has covered the offset originally requested. Can cause data corruption when multiple processes are performing writeout on different areas of the same file. Quite difficult to hit though. SGI Modid: xfs-linux:xfs-kern:22377a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig . --- fs/xfs/linux-2.6/xfs_aops.c | 68 ++++++++++++++++++++++++++------------------- fs/xfs/xfs_iomap.c | 20 +++++++------ fs/xfs/xfs_iomap.h | 7 ++--- fs/xfs/xfs_mount.h | 7 +++-- 4 files changed, 56 insertions(+), 46 deletions(-) (limited to 'fs') diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 1edd3b694332..9278e9aba9ba 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c @@ -558,7 +558,8 @@ xfs_submit_page( int i; BUG_ON(PageWriteback(page)); - set_page_writeback(page); + if (bh_count) + set_page_writeback(page); if (clear_dirty) clear_page_dirty(page); unlock_page(page); @@ -578,9 +579,6 @@ xfs_submit_page( if (probed_page && clear_dirty) wbc->nr_to_write--; /* Wrote an "extra" page */ - } else { - end_page_writeback(page); - wbc->pages_skipped++; /* We didn't write this page */ } } @@ -602,21 +600,26 @@ xfs_convert_page( { struct buffer_head *bh_arr[MAX_BUF_PER_PAGE], *bh, *head; xfs_iomap_t *mp = iomapp, *tmp; - unsigned long end, offset; - pgoff_t end_index; - int i = 0, index = 0; + unsigned long offset, end_offset; + int index = 0; int bbits = inode->i_blkbits; + int len, page_dirty; - end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT; - if (page->index < end_index) { - end = PAGE_CACHE_SIZE; - } else { - end = i_size_read(inode) & (PAGE_CACHE_SIZE-1); - } + end_offset = (i_size_read(inode) & (PAGE_CACHE_SIZE - 1)); + + /* + * page_dirty is initially a count of buffers on the page before + * EOF and is decrememted as we move each into a cleanable state. + */ + len = 1 << inode->i_blkbits; + end_offset = max(end_offset, PAGE_CACHE_SIZE); + end_offset = roundup(end_offset, len); + page_dirty = end_offset / len; + + offset = 0; bh = head = page_buffers(page); do { - offset = i << bbits; - if (offset >= end) + if (offset >= end_offset) break; if (!(PageUptodate(page) || buffer_uptodate(bh))) continue; @@ -625,6 +628,7 @@ xfs_convert_page( if (startio) { lock_buffer(bh); bh_arr[index++] = bh; + page_dirty--; } continue; } @@ -657,10 +661,11 @@ xfs_convert_page( unlock_buffer(bh); mark_buffer_dirty(bh); } - } while (i++, (bh = bh->b_this_page) != head); + page_dirty--; + } while (offset += len, (bh = bh->b_this_page) != head); - if (startio) { - xfs_submit_page(page, wbc, bh_arr, index, 1, index == i); + if (startio && index) { + xfs_submit_page(page, wbc, bh_arr, index, 1, !page_dirty); } else { unlock_page(page); } @@ -743,19 +748,22 @@ xfs_page_state_convert( } } - offset = (loff_t)page->index << PAGE_CACHE_SHIFT; end_offset = min_t(unsigned long long, - offset + PAGE_CACHE_SIZE, i_size_read(inode)); - - bh = head = page_buffers(page); - iomp = NULL; + (loff_t)(page->index + 1) << PAGE_CACHE_SHIFT, offset); + offset = (loff_t)page->index << PAGE_CACHE_SHIFT; /* - * page_dirty is initially a count of buffers on the page and - * is decrememted as we move each into a cleanable state. + * page_dirty is initially a count of buffers on the page before + * EOF and is decrememted as we move each into a cleanable state. */ - len = bh->b_size; - page_dirty = PAGE_CACHE_SIZE / len; + len = 1 << inode->i_blkbits; + p_offset = max(p_offset, PAGE_CACHE_SIZE); + p_offset = roundup(p_offset, len); + page_dirty = p_offset / len; + + iomp = NULL; + p_offset = 0; + bh = head = page_buffers(page); do { if (offset >= end_offset) @@ -877,8 +885,10 @@ xfs_page_state_convert( if (uptodate && bh == head) SetPageUptodate(page); - if (startio) - xfs_submit_page(page, wbc, bh_arr, cnt, 0, 1); + if (startio) { + WARN_ON(page_dirty); + xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty); + } if (iomp) { offset = (iomp->iomap_offset + iomp->iomap_bsize - 1) >> diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 3826e8f0e28a..b291a2b53579 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -308,7 +308,8 @@ phase2: break; } - error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, &imap, &nimaps); + error = XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, + &imap, &nimaps); break; case BMAPI_UNWRITTEN: lockmode = 0; @@ -746,6 +747,8 @@ write_map: int xfs_iomap_write_allocate( xfs_inode_t *ip, + loff_t offset, + size_t count, xfs_bmbt_irec_t *map, int *retmap) { @@ -770,9 +773,9 @@ xfs_iomap_write_allocate( if ((error = XFS_QM_DQATTACH(mp, ip, 0))) return XFS_ERROR(error); - offset_fsb = map->br_startoff; + offset_fsb = XFS_B_TO_FSBT(mp, offset); count_fsb = map->br_blockcount; - map_start_fsb = offset_fsb; + map_start_fsb = map->br_startoff; XFS_STATS_ADD(xs_xstrat_bytes, XFS_FSB_TO_B(mp, count_fsb)); @@ -868,9 +871,9 @@ xfs_iomap_write_allocate( imap[i].br_startoff, imap[i].br_blockcount,imap[i].br_state); } - if ((map->br_startoff >= imap[i].br_startoff) && - (map->br_startoff < (imap[i].br_startoff + - imap[i].br_blockcount))) { + if ((offset_fsb >= imap[i].br_startoff) && + (offset_fsb < (imap[i].br_startoff + + imap[i].br_blockcount))) { *map = imap[i]; *retmap = 1; XFS_STATS_INC(xs_xstrat_quick); @@ -883,9 +886,8 @@ xfs_iomap_write_allocate( * file, just surrounding data, try again. */ nimaps--; - offset_fsb = imap[nimaps].br_startoff + - imap[nimaps].br_blockcount; - map_start_fsb = offset_fsb; + map_start_fsb = imap[nimaps].br_startoff + + imap[nimaps].br_blockcount; } trans_cancel: diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 31c91087cb33..287895a3adc1 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -29,9 +29,6 @@ * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ - - - #ifndef __XFS_IOMAP_H__ #define __XFS_IOMAP_H__ @@ -56,7 +53,7 @@ typedef enum { BMAPI_UNWRITTEN = (1 << 3), /* unwritten extents to real extents */ /* modifiers */ BMAPI_IGNSTATE = (1 << 4), /* ignore unwritten state on read */ - BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ + BMAPI_DIRECT = (1 << 5), /* direct instead of buffered write */ BMAPI_MMAP = (1 << 6), /* allocate for mmap write */ BMAPI_SYNC = (1 << 7), /* sync write to flush delalloc space */ BMAPI_TRYLOCK = (1 << 8), /* non-blocking request */ @@ -100,7 +97,7 @@ extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t, int, struct xfs_bmbt_irec *, int *, int); extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int, struct xfs_bmbt_irec *, int *); -extern int xfs_iomap_write_allocate(struct xfs_inode *, +extern int xfs_iomap_write_allocate(struct xfs_inode *, loff_t, size_t, struct xfs_bmbt_irec *, int *); extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 1b968471ec8b..8ffb65dc110d 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -216,7 +216,8 @@ typedef int (*xfs_iomap_write_delay_t)( void *, loff_t, size_t, int, struct xfs_bmbt_irec *, int *); typedef int (*xfs_iomap_write_allocate_t)( - void *, struct xfs_bmbt_irec *, int *); + void *, loff_t, size_t, + struct xfs_bmbt_irec *, int *); typedef int (*xfs_iomap_write_unwritten_t)( void *, loff_t, size_t); typedef uint (*xfs_lck_map_shared_t)(void *); @@ -258,9 +259,9 @@ typedef struct xfs_ioops { #define XFS_IOMAP_WRITE_DELAY(mp, io, offset, count, flags, mval, nmap) \ (*(mp)->m_io_ops.xfs_iomap_write_delay) \ ((io)->io_obj, offset, count, flags, mval, nmap) -#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, mval, nmap) \ +#define XFS_IOMAP_WRITE_ALLOCATE(mp, io, offset, count, mval, nmap) \ (*(mp)->m_io_ops.xfs_iomap_write_allocate) \ - ((io)->io_obj, mval, nmap) + ((io)->io_obj, offset, count, mval, nmap) #define XFS_IOMAP_WRITE_UNWRITTEN(mp, io, offset, count) \ (*(mp)->m_io_ops.xfs_iomap_write_unwritten) \ ((io)->io_obj, offset, count) -- cgit v1.2.3 From f403b7f452e4347f6af14c1f3c47bce758eb6337 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 5 May 2005 13:33:40 -0700 Subject: [XFS] Cleanup use of loff_t vs xfs_off_t in the core code. SGI Modid: xfs-linux:xfs-kern:22378a Signed-off-by: Nathan Scott Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_dfrag.c | 2 +- fs/xfs/xfs_iomap.c | 8 ++++---- fs/xfs/xfs_iomap.h | 20 ++++++++++---------- fs/xfs/xfs_mount.h | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'fs') diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 08d551a17347..63abdc2ac7f4 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c @@ -182,7 +182,7 @@ xfs_swapext( if (VN_CACHED(tvp) != 0) xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore), - (loff_t)0, 0, 0); + (xfs_off_t)0, 0, 0); /* Verify O_DIRECT for ftmp */ if (VN_CACHED(tvp) != 0) { diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index b291a2b53579..991f8a61f7c4 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -366,7 +366,7 @@ xfs_flush_space( int xfs_iomap_write_direct( xfs_inode_t *ip, - loff_t offset, + xfs_off_t offset, size_t count, int flags, xfs_bmbt_irec_t *ret_imap, @@ -542,7 +542,7 @@ error_out: int xfs_iomap_write_delay( xfs_inode_t *ip, - loff_t offset, + xfs_off_t offset, size_t count, int ioflag, xfs_bmbt_irec_t *ret_imap, @@ -747,7 +747,7 @@ write_map: int xfs_iomap_write_allocate( xfs_inode_t *ip, - loff_t offset, + xfs_off_t offset, size_t count, xfs_bmbt_irec_t *map, int *retmap) @@ -901,7 +901,7 @@ error0: int xfs_iomap_write_unwritten( xfs_inode_t *ip, - loff_t offset, + xfs_off_t offset, size_t count) { xfs_mount_t *mp = ip->i_mount; diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 287895a3adc1..4daaa5212102 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003,2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -64,13 +64,13 @@ typedef enum { /* * xfs_iomap_t: File system I/O map * - * The iomap_bn field is expressed in 512-byte blocks, and is where the + * The iomap_bn field is expressed in 512-byte blocks, and is where the * mapping starts on disk. * * The iomap_offset, iomap_bsize and iomap_delta fields are in bytes. * iomap_offset is the offset of the mapping in the file itself. - * iomap_bsize is the size of the mapping, iomap_delta is the - * desired data's offset into the mapping, given the offset supplied + * iomap_bsize is the size of the mapping, iomap_delta is the + * desired data's offset into the mapping, given the offset supplied * to the file I/O map routine. * * When a request is made to read beyond the logical end of the object, @@ -81,8 +81,8 @@ typedef enum { typedef struct xfs_iomap { xfs_daddr_t iomap_bn; /* first 512b blk of mapping */ xfs_buftarg_t *iomap_target; - loff_t iomap_offset; /* offset of mapping, bytes */ - loff_t iomap_bsize; /* size of mapping, bytes */ + xfs_off_t iomap_offset; /* offset of mapping, bytes */ + xfs_off_t iomap_bsize; /* size of mapping, bytes */ size_t iomap_delta; /* offset into mapping, bytes */ iomap_flags_t iomap_flags; } xfs_iomap_t; @@ -93,12 +93,12 @@ struct xfs_bmbt_irec; extern int xfs_iomap(struct xfs_iocore *, xfs_off_t, ssize_t, int, struct xfs_iomap *, int *); -extern int xfs_iomap_write_direct(struct xfs_inode *, loff_t, size_t, +extern int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, int, struct xfs_bmbt_irec *, int *, int); -extern int xfs_iomap_write_delay(struct xfs_inode *, loff_t, size_t, int, +extern int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int, struct xfs_bmbt_irec *, int *); -extern int xfs_iomap_write_allocate(struct xfs_inode *, loff_t, size_t, +extern int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, size_t, struct xfs_bmbt_irec *, int *); -extern int xfs_iomap_write_unwritten(struct xfs_inode *, loff_t, size_t); +extern int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, size_t); #endif /* __XFS_IOMAP_H__*/ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 8ffb65dc110d..30dd08fb9f57 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -210,16 +210,16 @@ typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, struct xfs_bmap_free *); typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); typedef int (*xfs_iomap_write_direct_t)( - void *, loff_t, size_t, int, + void *, xfs_off_t, size_t, int, struct xfs_bmbt_irec *, int *, int); typedef int (*xfs_iomap_write_delay_t)( - void *, loff_t, size_t, int, + void *, xfs_off_t, size_t, int, struct xfs_bmbt_irec *, int *); typedef int (*xfs_iomap_write_allocate_t)( - void *, loff_t, size_t, + void *, xfs_off_t, size_t, struct xfs_bmbt_irec *, int *); typedef int (*xfs_iomap_write_unwritten_t)( - void *, loff_t, size_t); + void *, xfs_off_t, size_t); typedef uint (*xfs_lck_map_shared_t)(void *); typedef void (*xfs_lock_t)(void *, uint); typedef void (*xfs_lock_demote_t)(void *, uint); -- cgit v1.2.3 From e422fd2c965ad1b0e4eadaabd0adb77e8a93e74e Mon Sep 17 00:00:00 2001 From: Andrea Arcangeli Date: Thu, 5 May 2005 16:15:04 -0700 Subject: [PATCH] avoid -ENOMEM due reclaimable slab caches This makes sure that reclaimable buffer headers and reclaimable inodes are accounted properly during the overcommit checks. Signed-off-by: Andrea Arcangeli Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 2 +- fs/inode.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 5f525b3c6d9f..6ed59497fd4d 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3115,7 +3115,7 @@ void __init buffer_init(void) bh_cachep = kmem_cache_create("buffer_head", sizeof(struct buffer_head), 0, - SLAB_PANIC, init_buffer_head, NULL); + SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_buffer_head, NULL); /* * Limit the bh occupancy to 10% of ZONE_NORMAL diff --git a/fs/inode.c b/fs/inode.c index af8fd78d2099..90a110feb713 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1336,7 +1336,7 @@ void __init inode_init(unsigned long mempages) /* inode slab cache */ inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), - 0, SLAB_PANIC, init_once, NULL); + 0, SLAB_RECLAIM_ACCOUNT|SLAB_PANIC, init_once, NULL); set_shrinker(DEFAULT_SEEKS, shrink_icache_memory); /* Hash may have been set up in inode_init_early */ -- cgit v1.2.3 From 51a141104a37369be2822f423ed4444aa34d26a2 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 May 2005 16:15:34 -0700 Subject: [PATCH] uml: hostfs failed mount handling This cleans up the error handling and fixes a crash if a hostfs mount fails. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hostfs/hostfs_kern.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index e6c63d9cac7b..14a0d339d036 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -991,13 +991,17 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) goto out_put; err = read_inode(root_inode); - if(err) - goto out_put; + if(err){ + /* No iput in this case because the dput does that for us */ + dput(sb->s_root); + sb->s_root = NULL; + goto out_free; + } return(0); out_put: - iput(root_inode); + iput(root_inode); out_free: kfree(name); out: -- cgit v1.2.3 From f3ddbdc6267c32223035ea9bb8456a2d86f65ba1 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 5 May 2005 16:15:45 -0700 Subject: [PATCH] fix race in __block_prepare_write Fix a race where __block_prepare_write can leak out an in-flight read against a bh if get_block returns an error. This can lead to the page becoming unlocked while the buffer is locked and the read still in flight. __mpage_writepage BUGs on this condition. BUG sighted on a 2-way Itanium2 system with 16K PAGE_SIZE running fsstress -v -d $DIR/tmp -n 1000 -p 1000 -l 2 where $DIR is a new ext2 filesystem with 4K blocks that is quite small (causing get_block to fail often with -ENOSPC). Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 6ed59497fd4d..af7c51ded2e1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1953,7 +1953,7 @@ static int __block_prepare_write(struct inode *inode, struct page *page, if (!buffer_mapped(bh)) { err = get_block(inode, block, bh, 1); if (err) - goto out; + break; if (buffer_new(bh)) { clear_buffer_new(bh); unmap_underlying_metadata(bh->b_bdev, @@ -1995,10 +1995,12 @@ static int __block_prepare_write(struct inode *inode, struct page *page, while(wait_bh > wait) { wait_on_buffer(*--wait_bh); if (!buffer_uptodate(*wait_bh)) - return -EIO; + err = -EIO; } - return 0; -out: + if (!err) + return err; + + /* Error case: */ /* * Zero out any newly allocated blocks to avoid exposing stale * data. If BH_New is set, we know that the block was newly -- cgit v1.2.3 From ad576e63e0c8b274a8558b8e05a6d0526e804dc0 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Thu, 5 May 2005 16:15:46 -0700 Subject: [PATCH] __block_write_full_page race fix When running fsstress -v -d $DIR/tmp -n 1000 -p 1000 -l 2 on an ext2 filesystem with 1024 byte block size, on SMP i386 with 4096 byte page size over loopback to an image file on a tmpfs filesystem, I would very quickly hit BUG_ON(!buffer_async_write(bh)); in fs/buffer.c:end_buffer_async_write It seems that more than one request would be submitted for a given bh at a time. What would happen is the following: 2 threads doing __mpage_writepages on the same page. Thread 1 - lock the page first, and enter __block_write_full_page. Thread 1 - (eg.) mark_buffer_async_write on the first 2 buffers. Thread 1 - set page writeback, unlock page. Thread 2 - lock page, wait on page writeback Thread 1 - submit_bh on the first 2 buffers. => both requests complete, none of the page buffers are async_write, end_page_writeback is called. Thread 2 - wakes up. enters __block_write_full_page. Thread 2 - mark_buffer_async_write on (eg.) the last buffer Thread 1 - finds the last buffer has async_write set, submit_bh on that. Thread 2 - submit_bh on the last buffer. => oops. So change __block_write_full_page to explicitly keep track of the last bh we need to issue, so we don't touch anything after issuing the last request. Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index af7c51ded2e1..bc75f2e7b274 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1751,7 +1751,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, int err; sector_t block; sector_t last_block; - struct buffer_head *bh, *head; + struct buffer_head *bh, *head, *last_bh = NULL; int nr_underway = 0; BUG_ON(!PageLocked(page)); @@ -1809,7 +1809,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, } while (bh != head); do { - get_bh(bh); if (!buffer_mapped(bh)) continue; /* @@ -1827,6 +1826,8 @@ static int __block_write_full_page(struct inode *inode, struct page *page, } if (test_clear_buffer_dirty(bh)) { mark_buffer_async_write(bh); + get_bh(bh); + last_bh = bh; } else { unlock_buffer(bh); } @@ -1845,10 +1846,13 @@ static int __block_write_full_page(struct inode *inode, struct page *page, if (buffer_async_write(bh)) { submit_bh(WRITE, bh); nr_underway++; + put_bh(bh); + if (bh == last_bh) + break; } - put_bh(bh); bh = next; } while (bh != head); + bh = head; err = 0; done: @@ -1887,10 +1891,11 @@ recover: bh = head; /* Recovery: lock and submit the mapped buffers */ do { - get_bh(bh); if (buffer_mapped(bh) && buffer_dirty(bh)) { lock_buffer(bh); mark_buffer_async_write(bh); + get_bh(bh); + last_bh = bh; } else { /* * The buffer may have been set dirty during @@ -1909,10 +1914,13 @@ recover: clear_buffer_dirty(bh); submit_bh(WRITE, bh); nr_underway++; + put_bh(bh); + if (bh == last_bh) + break; } - put_bh(bh); bh = next; } while (bh != head); + bh = head; goto done; } -- cgit v1.2.3 From 05937baae9fc27b64bcd4378da7d2b14edf7931c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 5 May 2005 16:15:47 -0700 Subject: [PATCH] __block_write_full_page speedup Remove all those get_bh()'s and put_bh()'s by extending lock_page() to cover the troublesome regions. (get_bh() and put_bh() happen every time whereas contention on a page's lock in there happens basically never). Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index bc75f2e7b274..6f2c3303a443 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1826,7 +1826,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, } if (test_clear_buffer_dirty(bh)) { mark_buffer_async_write(bh); - get_bh(bh); last_bh = bh; } else { unlock_buffer(bh); @@ -1839,20 +1838,19 @@ static int __block_write_full_page(struct inode *inode, struct page *page, */ BUG_ON(PageWriteback(page)); set_page_writeback(page); - unlock_page(page); do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { submit_bh(WRITE, bh); nr_underway++; - put_bh(bh); if (bh == last_bh) break; } bh = next; } while (bh != head); bh = head; + unlock_page(page); err = 0; done: @@ -1894,7 +1892,6 @@ recover: if (buffer_mapped(bh) && buffer_dirty(bh)) { lock_buffer(bh); mark_buffer_async_write(bh); - get_bh(bh); last_bh = bh; } else { /* @@ -1914,7 +1911,6 @@ recover: clear_buffer_dirty(bh); submit_bh(WRITE, bh); nr_underway++; - put_bh(bh); if (bh == last_bh) break; } -- cgit v1.2.3 From f0fbd5fc09b20f7ba7bc8c80be33e39925bb38e1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 5 May 2005 16:15:48 -0700 Subject: [PATCH] __block_write_full_page() simplification The `last_bh' logic probably isn't worth much. In those situations where only the front part of the page is being written out we will save some looping but in the vastly more common case of an all-page writeout if just adds more code. Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'fs') diff --git a/fs/buffer.c b/fs/buffer.c index 6f2c3303a443..91ace8034bf7 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1751,7 +1751,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, int err; sector_t block; sector_t last_block; - struct buffer_head *bh, *head, *last_bh = NULL; + struct buffer_head *bh, *head; int nr_underway = 0; BUG_ON(!PageLocked(page)); @@ -1826,7 +1826,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, } if (test_clear_buffer_dirty(bh)) { mark_buffer_async_write(bh); - last_bh = bh; } else { unlock_buffer(bh); } @@ -1844,12 +1843,9 @@ static int __block_write_full_page(struct inode *inode, struct page *page, if (buffer_async_write(bh)) { submit_bh(WRITE, bh); nr_underway++; - if (bh == last_bh) - break; } bh = next; } while (bh != head); - bh = head; unlock_page(page); err = 0; @@ -1892,7 +1888,6 @@ recover: if (buffer_mapped(bh) && buffer_dirty(bh)) { lock_buffer(bh); mark_buffer_async_write(bh); - last_bh = bh; } else { /* * The buffer may have been set dirty during @@ -1911,12 +1906,9 @@ recover: clear_buffer_dirty(bh); submit_bh(WRITE, bh); nr_underway++; - if (bh == last_bh) - break; } bh = next; } while (bh != head); - bh = head; goto done; } -- cgit v1.2.3 From dfc1e148542f6f4951fd59e32c14a7368356db9d Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 5 May 2005 16:15:51 -0700 Subject: [PATCH] remove BK documentation There's no longer a reason to document the obsolete BK usage. Signed-off-by: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/00-INDEX | 2 - Documentation/BK-usage/00-INDEX | 51 ------ Documentation/BK-usage/bk-kernel-howto.txt | 283 ----------------------------- Documentation/BK-usage/bk-make-sum | 34 ---- Documentation/BK-usage/bksend | 36 ---- Documentation/BK-usage/bz64wrap | 41 ----- Documentation/BK-usage/cpcset | 36 ---- Documentation/BK-usage/cset-to-linus | 49 ----- Documentation/BK-usage/csets-to-patches | 44 ----- Documentation/BK-usage/gcapatch | 8 - Documentation/BK-usage/unbz64wrap | 25 --- fs/cifs/README | 6 +- 12 files changed, 3 insertions(+), 612 deletions(-) delete mode 100644 Documentation/BK-usage/00-INDEX delete mode 100644 Documentation/BK-usage/bk-kernel-howto.txt delete mode 100755 Documentation/BK-usage/bk-make-sum delete mode 100755 Documentation/BK-usage/bksend delete mode 100755 Documentation/BK-usage/bz64wrap delete mode 100755 Documentation/BK-usage/cpcset delete mode 100755 Documentation/BK-usage/cset-to-linus delete mode 100755 Documentation/BK-usage/csets-to-patches delete mode 100755 Documentation/BK-usage/gcapatch delete mode 100755 Documentation/BK-usage/unbz64wrap (limited to 'fs') diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 72dc90f8f4a7..8de8a01a2474 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -12,8 +12,6 @@ Following translations are available on the WWW: 00-INDEX - this file. -BK-usage/ - - directory with info on BitKeeper. BUG-HUNTING - brute force method of doing binary search of patches to find bug. Changes diff --git a/Documentation/BK-usage/00-INDEX b/Documentation/BK-usage/00-INDEX deleted file mode 100644 index 82768784ea52..000000000000 --- a/Documentation/BK-usage/00-INDEX +++ /dev/null @@ -1,51 +0,0 @@ -bk-kernel-howto.txt: Description of kernel workflow under BitKeeper - -bk-make-sum: Create summary of changesets in one repository and not -another, typically in preparation to be sent to an upstream maintainer. -Typical usage: - cd my-updated-repo - bk-make-sum ~/repo/original-repo - mv /tmp/linus.txt ../original-repo.txt - -bksend: Create readable text output containing summary of changes, GNU -patch of the changes, and BK metadata of changes (as needed for proper -importing into BitKeeper by an upstream maintainer). This output is -suitable for emailing BitKeeper changes. The recipient of this output -may pipe it directly to 'bk receive'. - -bz64wrap: helper script. Uncompressed input is piped to this script, -which compresses its input, and then outputs the uu-/base64-encoded -version of the compressed input. - -cpcset: Copy changeset between unrelated repositories. -Attempts to preserve changeset user, user address, description, in -addition to the changeset (the patch) itself. -Typical usage: - cd my-updated-repo - bk changes # looking for a changeset... - cpcset 1.1511 . ../another-repo - -csets-to-patches: Produces a delta of two BK repositories, in the form -of individual files, each containing a single cset as a GNU patch. -Output is several files, each with the filename "/tmp/rev-$REV.patch" -Typical usage: - cd my-updated-repo - bk changes -L ~/repo/original-repo 2>&1 | \ - perl csets-to-patches - -cset-to-linus: Produces a delta of two BK repositories, in the form of -changeset descriptions, with 'diffstat' output created for each -individual changset. -Typical usage: - cd my-updated-repo - bk changes -L ~/repo/original-repo 2>&1 | \ - perl cset-to-linus > summary.txt - -gcapatch: Generates patch containing changes in local repository. -Typical usage: - cd my-updated-repo - gcapatch > foo.patch - -unbz64wrap: Reverse an encoded, compressed data stream created by -bz64wrap into an uncompressed, typically text/plain output. - diff --git a/Documentation/BK-usage/bk-kernel-howto.txt b/Documentation/BK-usage/bk-kernel-howto.txt deleted file mode 100644 index b7b9075d2910..000000000000 --- a/Documentation/BK-usage/bk-kernel-howto.txt +++ /dev/null @@ -1,283 +0,0 @@ - - Doing the BK Thing, Penguin-Style - - - - -This set of notes is intended mainly for kernel developers, occasional -or full-time, but sysadmins and power users may find parts of it useful -as well. It assumes at least a basic familiarity with CVS, both at a -user level (use on the cmd line) and at a higher level (client-server model). -Due to the author's background, an operation may be described in terms -of CVS, or in terms of how that operation differs from CVS. - -This is -not- intended to be BitKeeper documentation. Always run -"bk help " or in X "bk helptool " for reference -documentation. - - -BitKeeper Concepts ------------------- - -In the true nature of the Internet itself, BitKeeper is a distributed -system. When applied to revision control, this means doing away with -client-server, and changing to a parent-child model... essentially -peer-to-peer. On the developer's end, this also represents a -fundamental disruption in the standard workflow of changes, commits, -and merges. You will need to take a few minutes to think about -how to best work under BitKeeper, and re-optimize things a bit. -In some sense it is a bit radical, because it might described as -tossing changes out into a maelstrom and having them magically -land at the right destination... but I'm getting ahead of myself. - -Let's start with this progression: -Each BitKeeper source tree on disk is a repository unto itself. -Each repository has a parent (except the root/original, of course). -Each repository contains a set of a changesets ("csets"). -Each cset is one or more changed files, bundled together. - -Each tree is a repository, so all changes are checked into the local -tree. When a change is checked in, all modified files are grouped -into a logical unit, the changeset. Internally, BK links these -changesets in a tree, representing various converging and diverging -lines of development. These changesets are the bread and butter of -the BK system. - -After the concept of changesets, the next thing you need to get used -to is having multiple copies of source trees lying around. This -really- -takes some getting used to, for some people. Separate source trees -are the means in BitKeeper by which you delineate parallel lines -of development, both minor and major. What would be branches in -CVS become separate source trees, or "clones" in BitKeeper [heh, -or Star Wars] terminology. - -Clones and changesets are the tools from which most of the power of -BitKeeper is derived. As mentioned earlier, each clone has a parent, -the tree used as the source when the new clone was created. In a -CVS-like setup, the parent would be a remote server on the Internet, -and the child is your local clone of that tree. - -Once you have established a common baseline between two source trees -- -a common parent -- then you can merge changesets between those two -trees with ease. Merging changes into a tree is called a "pull", and -is analagous to 'cvs update'. A pull downloads all the changesets in -the remote tree you do not have, and merges them. Sending changes in -one tree to another tree is called a "push". Push sends all changes -in the local tree the remote does not yet have, and merges them. - -From these concepts come some initial command examples: - -1) bk clone -q http://linux.bkbits.net/linux-2.5 linus-2.5 -Download a 2.5 stock kernel tree, naming it "linus-2.5" in the local dir. -The "-q" disables listing every single file as it is downloaded. - -2) bk clone -ql linus-2.5 alpha-2.5 -Create a separate source tree for the Alpha AXP architecture. -The "-l" uses hard links instead of copying data, since both trees are -on the local disk. You can also replace the above with "bk lclone -q ..." - -You only clone a tree -once-. After cloning the tree lives a long time -on disk, being updating by pushes and pulls. - -3) cd alpha-2.5 ; bk pull http://gkernel.bkbits.net/alpha-2.5 -Download changes in "alpha-2.5" repository which are not present -in the local repository, and merge them into the source tree. - -4) bk -r co -q -Because every tree is a repository, files must be checked out before -they will be in their standard places in the source tree. - -5) bk vi fs/inode.c # example change... - bk citool # checkin, using X tool - bk push bk://gkernel@bkbits.net/alpha-2.5 # upload change -Typical example of a BK sequence that would replace the analagous CVS -situation, - vi fs/inode.c - cvs commit - -As this is just supposed to be a quick BK intro, for more in-depth -tutorials, live working demos, and docs, see http://www.bitkeeper.com/ - - - -BK and Kernel Development Workflow ----------------------------------- -Currently the latest 2.5 tree is available via "bk clone $URL" -and "bk pull $URL" at http://linux.bkbits.net/linux-2.5 -This should change in a few weeks to a kernel.org URL. - - -A big part of using BitKeeper is organizing the various trees you have -on your local disk, and organizing the flow of changes among those -trees, and remote trees. If one were to graph the relationships between -a desired BK setup, you are likely to see a few-many-few graph, like -this: - - linux-2.5 - | - merge-to-linus-2.5 - / | | - / | | - vm-hacks bugfixes filesys personal-hacks - \ | | / - \ | | / - \ | | / - testing-and-validation - -Since a "bk push" sends all changes not in the target tree, and -since a "bk pull" receives all changes not in the source tree, you want -to make sure you are only pushing specific changes to the desired tree, -not all changes from "peer parent" trees. For example, pushing a change -from the testing-and-validation tree would probably be a bad idea, -because it will push all changes from vm-hacks, bugfixes, filesys, and -personal-hacks trees into the target tree. - -One would typically work on only one "theme" at a time, either -vm-hacks or bugfixes or filesys, keeping those changes isolated in -their own tree during development, and only merge the isolated with -other changes when going upstream (to Linus or other maintainers) or -downstream (to your "union" trees, like testing-and-validation above). - -It should be noted that some of this separation is not just recommended -practice, it's actually [for now] -enforced- by BitKeeper. BitKeeper -requires that changesets maintain a certain order, which is the reason -that "bk push" sends all local changesets the remote doesn't have. This -separation may look like a lot of wasted disk space at first, but it -helps when two unrelated changes may "pollute" the same area of code, or -don't follow the same pace of development, or any other of the standard -reasons why one creates a development branch. - -Small development branches (clones) will appear and disappear: - - -------- A --------- B --------- C --------- D ------- - \ / - -----short-term devel branch----- - -While long-term branches will parallel a tree (or trees), with period -merge points. In this first example, we pull from a tree (pulls, -"\") periodically, such as what occurs when tracking changes in a -vendor tree, never pushing changes back up the line: - - -------- A --------- B --------- C --------- D ------- - \ \ \ - ----long-term devel branch----------------- - -And then a more common case in Linux kernel development, a long term -branch with periodic merges back into the tree (pushes, "/"): - - -------- A --------- B --------- C --------- D ------- - \ \ / \ - ----long-term devel branch----------------- - - - - - -Submitting Changes to Linus ---------------------------- -There's a bit of an art, or style, of submitting changes to Linus. -Since Linus's tree is now (you might say) fully integrated into the -distributed BitKeeper system, there are several prerequisites to -properly submitting a BitKeeper change. All these prereq's are just -general cleanliness of BK usage, so as people become experts at BK, feel -free to optimize this process further (assuming Linus agrees, of -course). - - - -0) Make sure your tree was originally cloned from the linux-2.5 tree -created by Linus. If your tree does not have this as its ancestor, it -is impossible to reliably exchange changesets. - - - -1) Pay attention to your commit text. The commit message that -accompanies each changeset you submit will live on forever in history, -and is used by Linus to accurately summarize the changes in each -pre-patch. Remember that there is no context, so - "fix for new scheduler changes" -would be too vague, but - "fix mips64 arch for new scheduler switch_to(), TIF_xxx semantics" -would be much better. - -You can and should use the command "bk comment -C" to update the -commit text, and improve it after the fact. This is very useful for -development: poor, quick descriptions during development, which get -cleaned up using "bk comment" before issuing the "bk push" to submit the -changes. - - - -2) Include an Internet-available URL for Linus to pull from, such as - - Pull from: http://gkernel.bkbits.net/net-drivers-2.5 - - - -3) Include a summary and "diffstat -p1" of each changeset that will be -downloaded, when Linus issues a "bk pull". The author auto-generates -these summaries using "bk changes -L ", to obtain a listing -of all the pending-to-send changesets, and their commit messages. - -It is important to show Linus what he will be downloading when he issues -a "bk pull", to reduce the time required to sift the changes once they -are downloaded to Linus's local machine. - -IMPORTANT NOTE: One of the features of BK is that your repository does -not have to be up to date, in order for Linus to receive your changes. -It is considered a courtesy to keep your repository fairly recent, to -lessen any potential merge work Linus may need to do. - - -4) Split up your changes. Each maintainer<->Linus situation is likely -to be slightly different here, so take this just as general advice. The -author splits up changes according to "themes" when merging with Linus. -Simultaneous pushes from local development go to special trees which -exist solely to house changes "queued" for Linus. Example of the trees: - - net-drivers-2.5 -- on-going net driver maintenance - vm-2.5 -- VM-related changes - fs-2.5 -- filesystem-related changes - -Linus then has much more freedom for pulling changes. He could (for -example) issue a "bk pull" on vm-2.5 and fs-2.5 trees, to merge their -changes, but hold off net-drivers-2.5 because of a change that needs -more discussion. - -Other maintainers may find that a single linus-pull-from tree is -adequate for passing BK changesets to him. - - - -Frequently Answered Questions ------------------------------ -1) How do I change the e-mail address shown in the changelog? -A. When you run "bk citool" or "bk commit", set environment - variables BK_USER and BK_HOST to the desired username - and host/domain name. - - -2) How do I use tags / get a diff between two kernel versions? -A. Pass the tags Linus uses to 'bk export'. - -ChangeSets are in a forward-progressing order, so it's pretty easy -to get a snapshot starting and ending at any two points in time. -Linus puts tags on each release and pre-release, so you could use -these two examples: - - bk export -tpatch -hdu -rv2.5.4,v2.5.5 | less - # creates patch-2.5.5 essentially - bk export -tpatch -du -rv2.5.5-pre1,v2.5.5 | less - # changes from pre1 to final - -A tag is just an alias for a specific changeset... and since changesets -are ordered, a tag is thus a marker for a specific point in time (or -specific state of the tree). - - -3) Is there an easy way to generate One Big Patch versus mainline, - for my long-lived kernel branch? -A. Yes. This requires BK 3.x, though. - - bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ - diff --git a/Documentation/BK-usage/bk-make-sum b/Documentation/BK-usage/bk-make-sum deleted file mode 100755 index 58ca46a0fcc6..000000000000 --- a/Documentation/BK-usage/bk-make-sum +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -e -# DIR=$HOME/BK/axp-2.5 -# cd $DIR - -LINUS_REPO=$1 -DIRBASE=`basename $PWD` - -{ -cat </dev/null - -cat < (:D: :I:)\n$each(:C:){ (:C:)\n}\n}' - - -} > /tmp/linus.txt - -cat < 13/02/2002 -# -# Add diffstat output after Changelog 21/02/2002 - -PROG=bksend - -usage() { - echo "usage: $PROG -r" - echo -e "\twhere is of the form '1.23', '1.23..', '1.23..1.27'," - echo -e "\tor '+' to indicate the most recent revision" - - exit 1 -} - -case $1 in --r) REV=$2; shift ;; --r*) REV=`echo $1 | sed 's/^-r//'` ;; -*) echo "$PROG: no revision given, you probably don't want that";; -esac - -[ -z "$REV" ] && usage - -echo "You can import this changeset into BK by piping this whole message to:" -echo "'| bk receive [path to repository]' or apply the patch as usual." - -SEP="\n===================================================================\n\n" -echo -e $SEP -env PAGER=/bin/cat bk changes -r$REV -echo -bk export -tpatch -du -h -r$REV | diffstat -echo; echo -bk export -tpatch -du -h -r$REV -echo -e $SEP -bk send -wgzip_uu -r$REV - diff --git a/Documentation/BK-usage/bz64wrap b/Documentation/BK-usage/bz64wrap deleted file mode 100755 index be780876849f..000000000000 --- a/Documentation/BK-usage/bz64wrap +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh - -# bz64wrap - the sending side of a bzip2 | base64 stream -# Andreas Dilger Jan 2002 - - -PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin - -# A program to generate base64 encoding on stdout -BASE64_ENCODE="uuencode -m /dev/stdout" -BASE64_BEGIN= -BASE64_END= - -BZIP=NO -BASE64=NO - -# Test if we have the bzip program installed -bzip2 -c /dev/null > /dev/null 2>&1 && BZIP=YES - -# Test if uuencode can handle the -m (MIME) encoding option -$BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES - -if [ $BASE64 = NO ]; then - BASE64_ENCODE=mimencode - BASE64_BEGIN="begin-base64 644 -" - BASE64_END="====" - - $BASE64_ENCODE < /dev/null > /dev/null 2>&1 && BASE64=YES -fi - -if [ $BZIP = NO -o $BASE64 = NO ]; then - echo "$0: can't use bz64 encoding: bzip2=$BZIP, $BASE64_ENCODE=$BASE64" - exit 1 -fi - -# Sadly, mimencode does not appear to have good "begin" and "end" markers -# like uuencode does, and it is picky about getting the right start/end of -# the base64 stream, so we handle this internally. -echo "$BASE64_BEGIN" -bzip2 -9 | $BASE64_ENCODE -echo "$BASE64_END" diff --git a/Documentation/BK-usage/cpcset b/Documentation/BK-usage/cpcset deleted file mode 100755 index b8faca97dab9..000000000000 --- a/Documentation/BK-usage/cpcset +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# -# Purpose: Copy changeset patch and description from one -# repository to another, unrelated one. -# -# usage: cpcset [revision] [from-repository] [to-repository] -# - -REV=$1 -FROM=$2 -TO=$3 -TMPF=/tmp/cpcset.$$ - -rm -f $TMPF* - -CWD_SAVE=`pwd` -cd $FROM -bk changes -r$REV | \ - grep -v '^ChangeSet' | \ - sed -e 's/^ //g' > $TMPF.log - -USERHOST=`bk changes -r$REV | grep '^ChangeSet' | awk '{print $4}'` -export BK_USER=`echo $USERHOST | awk '-F@' '{print $1}'` -export BK_HOST=`echo $USERHOST | awk '-F@' '{print $2}'` - -bk export -tpatch -hdu -r$REV > $TMPF.patch && \ -cd $CWD_SAVE && \ -cd $TO && \ -bk import -tpatch -CFR -y"`cat $TMPF.log`" $TMPF.patch . && \ -bk commit -y"`cat $TMPF.log`" - -rm -f $TMPF* - -echo changeset $REV copied. -echo "" - diff --git a/Documentation/BK-usage/cset-to-linus b/Documentation/BK-usage/cset-to-linus deleted file mode 100755 index d28a96f8c618..000000000000 --- a/Documentation/BK-usage/cset-to-linus +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -my ($lhs, $rev, $tmp, $rhs, $s); -my @cset_text = (); -my @pipe_text = (); -my $have_cset = 0; - -while (<>) { - next if /^---/; - - if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) { - &cset_rev if ($have_cset); - - $rev = $tmp; - $have_cset = 1; - - push(@cset_text, $_); - } - - elsif ($have_cset) { - push(@cset_text, $_); - } -} -&cset_rev if ($have_cset); -exit(0); - - -sub cset_rev { - my $empty_cset = 0; - - open PIPE, "bk export -tpatch -hdu -r $rev | diffstat -p1 2>/dev/null |" or die; - while ($s = ) { - $empty_cset = 1 if ($s =~ /0 files changed/); - push(@pipe_text, $s); - } - close(PIPE); - - if (! $empty_cset) { - print @cset_text; - print @pipe_text; - print "\n\n"; - } - - @pipe_text = (); - @cset_text = (); -} - diff --git a/Documentation/BK-usage/csets-to-patches b/Documentation/BK-usage/csets-to-patches deleted file mode 100755 index e2b81c35883f..000000000000 --- a/Documentation/BK-usage/csets-to-patches +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/perl -w - -use strict; - -my ($lhs, $rev, $tmp, $rhs, $s); -my @cset_text = (); -my @pipe_text = (); -my $have_cset = 0; - -while (<>) { - next if /^---/; - - if (($lhs, $tmp, $rhs) = (/^(ChangeSet\@)([^,]+)(, .*)$/)) { - &cset_rev if ($have_cset); - - $rev = $tmp; - $have_cset = 1; - - push(@cset_text, $_); - } - - elsif ($have_cset) { - push(@cset_text, $_); - } -} -&cset_rev if ($have_cset); -exit(0); - - -sub cset_rev { - my $empty_cset = 0; - - system("bk export -tpatch -du -r $rev > /tmp/rev-$rev.patch"); - - if (! $empty_cset) { - print @cset_text; - print @pipe_text; - print "\n\n"; - } - - @pipe_text = (); - @cset_text = (); -} - diff --git a/Documentation/BK-usage/gcapatch b/Documentation/BK-usage/gcapatch deleted file mode 100755 index aaeb17dc7c7f..000000000000 --- a/Documentation/BK-usage/gcapatch +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# -# Purpose: Generate GNU diff of local changes versus canonical top-of-tree -# -# Usage: gcapatch > foo.patch -# - -bk export -tpatch -hdu -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ diff --git a/Documentation/BK-usage/unbz64wrap b/Documentation/BK-usage/unbz64wrap deleted file mode 100755 index 4fc3e73e9a81..000000000000 --- a/Documentation/BK-usage/unbz64wrap +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -# unbz64wrap - the receiving side of a bzip2 | base64 stream -# Andreas Dilger Jan 2002 - -# Sadly, mimencode does not appear to have good "begin" and "end" markers -# like uuencode does, and it is picky about getting the right start/end of -# the base64 stream, so we handle this explicitly here. - -PATH=$PATH:/usr/bin:/usr/local/bin:/usr/freeware/bin - -if mimencode -u < /dev/null > /dev/null 2>&1 ; then - SHOW= - while read LINE; do - case $LINE in - begin-base64*) SHOW=YES ;; - ====) SHOW= ;; - *) [ "$SHOW" ] && echo "$LINE" ;; - esac - done | mimencode -u | bunzip2 - exit $? -else - cat - | uudecode -o /dev/stdout | bunzip2 - exit $? -fi diff --git a/fs/cifs/README b/fs/cifs/README index 7b4ac096cd11..e74df0c73256 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -32,9 +32,9 @@ the cifs download to your kernel build directory e.g. 6) make modules (or "make" if CIFS VFS not to be built as a module) For Linux 2.6: -1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper -at bk://linux.bkbits.net/linux-2.5) and change directory into the top -of the kernel directory tree (e.g. /usr/src/linux-2.5.73) +1) Download the kernel (e.g. from http://www.kernel.org) +and change directory into the top of the kernel directory tree +(e.g. /usr/src/linux-2.5.73) 2) make menuconfig (or make xconfig) 3) select cifs from within the network filesystem choices 4) save and exit -- cgit v1.2.3 From 2ef41634def0fcb0def3e3c90220c651ca478cb3 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Thu, 5 May 2005 16:15:59 -0700 Subject: [PATCH] remove do_sync parameter from __invalidate_device The only caller that ever sets it can call fsync_bdev itself easily. Also update some comments. Signed-off-by: Christoph Hellwig Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 2 +- drivers/block/genhd.c | 4 +++- fs/block_dev.c | 2 +- fs/inode.c | 21 +++------------------ include/linux/fs.h | 2 +- 5 files changed, 9 insertions(+), 22 deletions(-) (limited to 'fs') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 42dfa281a880..f0c1084b840f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3345,7 +3345,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g, struct block_device *bdev = opened_bdev[cnt]; if (!bdev || ITYPE(drive_state[cnt].fd_device) != type) continue; - __invalidate_device(bdev, 0); + __invalidate_device(bdev); } up(&open_lock); } else { diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index ab4db71375e0..8bbe01d4b487 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -14,6 +14,7 @@ #include #include #include +#include #define MAX_PROBE_HASH 255 /* random */ @@ -676,7 +677,8 @@ int invalidate_partition(struct gendisk *disk, int index) int res = 0; struct block_device *bdev = bdget_disk(disk, index); if (bdev) { - res = __invalidate_device(bdev, 1); + fsync_bdev(bdev); + res = __invalidate_device(bdev); bdput(bdev); } return res; diff --git a/fs/block_dev.c b/fs/block_dev.c index d19d07c49ad3..c0cbd1bc1a02 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -530,7 +530,7 @@ int check_disk_change(struct block_device *bdev) if (!bdops->media_changed(bdev->bd_disk)) return 0; - if (__invalidate_device(bdev, 0)) + if (__invalidate_device(bdev)) printk("VFS: busy inodes on changed media.\n"); if (bdops->revalidate_disk) diff --git a/fs/inode.c b/fs/inode.c index 90a110feb713..801fe7f36280 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -26,7 +26,6 @@ * This is needed for the following functions: * - inode_has_buffers * - invalidate_inode_buffers - * - fsync_bdev * - invalidate_bdev * * FIXME: remove all knowledge of the buffer layer from this file @@ -332,14 +331,6 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose) return busy; } -/* - * This is a two-stage process. First we collect all - * offending inodes onto the throw-away list, and in - * the second stage we actually dispose of them. This - * is because we don't want to sleep while messing - * with the global lists.. - */ - /** * invalidate_inodes - discard the inodes on a device * @sb: superblock @@ -366,16 +357,11 @@ int invalidate_inodes(struct super_block * sb) EXPORT_SYMBOL(invalidate_inodes); -int __invalidate_device(struct block_device *bdev, int do_sync) +int __invalidate_device(struct block_device *bdev) { - struct super_block *sb; - int res; + struct super_block *sb = get_super(bdev); + int res = 0; - if (do_sync) - fsync_bdev(bdev); - - res = 0; - sb = get_super(bdev); if (sb) { /* * no need to lock the super, get_super holds the @@ -390,7 +376,6 @@ int __invalidate_device(struct block_device *bdev, int do_sync) invalidate_bdev(bdev, 0); return res; } - EXPORT_SYMBOL(__invalidate_device); static int can_unuse(struct inode *inode) diff --git a/include/linux/fs.h b/include/linux/fs.h index 4edba067a717..0180102dace1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1341,7 +1341,7 @@ extern int fs_may_remount_ro(struct super_block *); extern int check_disk_change(struct block_device *); extern int invalidate_inodes(struct super_block *); -extern int __invalidate_device(struct block_device *, int); +extern int __invalidate_device(struct block_device *); extern int invalidate_partition(struct gendisk *, int); unsigned long invalidate_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t end); -- cgit v1.2.3 From d17d7fa44dbe1f12031773e27eda9e939024a037 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 5 May 2005 16:16:02 -0700 Subject: [PATCH] revert ext3-writepages-support-for-writeback-mode This had a fatal lock ranking bug: we do journal_start outside mpage_writepages()'s lock_page(). Revert the whole thing, think again. Credit-to: Jan Kara For identifying the bug. Cc: Badari Pulavarty Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/inode.c | 46 ---------------------------------------------- fs/mpage.c | 12 +----------- include/linux/mpage.h | 3 --- 3 files changed, 1 insertion(+), 60 deletions(-) (limited to 'fs') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index ea5888688f94..0d5fa73b18dc 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -844,12 +844,6 @@ get_block: return ret; } -static int ext3_writepages_get_block(struct inode *inode, sector_t iblock, - struct buffer_head *bh, int create) -{ - return ext3_direct_io_get_blocks(inode, iblock, 1, bh, create); -} - /* * `handle' can be NULL if create is zero */ @@ -1323,45 +1317,6 @@ out_fail: return ret; } -static int -ext3_writeback_writepage_helper(struct page *page, - struct writeback_control *wbc) -{ - return block_write_full_page(page, ext3_get_block, wbc); -} - -static int -ext3_writeback_writepages(struct address_space *mapping, - struct writeback_control *wbc) -{ - struct inode *inode = mapping->host; - handle_t *handle = NULL; - int err, ret = 0; - - if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) - return ret; - - handle = ext3_journal_start(inode, ext3_writepage_trans_blocks(inode)); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - return ret; - } - - ret = __mpage_writepages(mapping, wbc, ext3_writepages_get_block, - ext3_writeback_writepage_helper); - - /* - * Need to reaquire the handle since ext3_writepages_get_block() - * can restart the handle - */ - handle = journal_current_handle(); - - err = ext3_journal_stop(handle); - if (!ret) - ret = err; - return ret; -} - static int ext3_writeback_writepage(struct page *page, struct writeback_control *wbc) { @@ -1599,7 +1554,6 @@ static struct address_space_operations ext3_writeback_aops = { .readpage = ext3_readpage, .readpages = ext3_readpages, .writepage = ext3_writeback_writepage, - .writepages = ext3_writeback_writepages, .sync_page = block_sync_page, .prepare_write = ext3_prepare_write, .commit_write = ext3_writeback_commit_write, diff --git a/fs/mpage.c b/fs/mpage.c index 32c7c8fcfce7..68db5256a727 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -626,15 +626,6 @@ out: int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block) -{ - return __mpage_writepages(mapping, wbc, get_block, - mapping->a_ops->writepage); -} - -int -__mpage_writepages(struct address_space *mapping, - struct writeback_control *wbc, get_block_t get_block, - writepage_t writepage_fn) { struct backing_dev_info *bdi = mapping->backing_dev_info; struct bio *bio = NULL; @@ -725,7 +716,7 @@ retry: } else { bio = __mpage_writepage(bio, page, get_block, &last_block_in_bio, &ret, wbc, - writepage_fn); + page->mapping->a_ops->writepage); } if (unlikely(ret == WRITEPAGE_ACTIVATE)) unlock_page(page); @@ -755,7 +746,6 @@ retry: return ret; } EXPORT_SYMBOL(mpage_writepages); -EXPORT_SYMBOL(__mpage_writepages); int mpage_writepage(struct page *page, get_block_t get_block, struct writeback_control *wbc) diff --git a/include/linux/mpage.h b/include/linux/mpage.h index dea1b0083661..3ca880463c47 100644 --- a/include/linux/mpage.h +++ b/include/linux/mpage.h @@ -20,9 +20,6 @@ int mpage_writepages(struct address_space *mapping, struct writeback_control *wbc, get_block_t get_block); int mpage_writepage(struct page *page, get_block_t *get_block, struct writeback_control *wbc); -int __mpage_writepages(struct address_space *mapping, - struct writeback_control *wbc, get_block_t get_block, - writepage_t writepage); static inline int generic_writepages(struct address_space *mapping, struct writeback_control *wbc) -- cgit v1.2.3 From 75c96f85845a6707b0f9916cb263cb3584f7d48f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 5 May 2005 16:16:09 -0700 Subject: [PATCH] make some things static This patch makes some needlessly global identifiers static. Signed-off-by: Adrian Bunk Acked-by: Arjan van de Ven Acked-by: Trond Myklebust Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/rd.c | 2 +- drivers/cdrom/cdu31a.c | 6 +++--- drivers/cdrom/mcdx.c | 28 +++++++++++++--------------- drivers/cdrom/sbpcd.c | 2 +- drivers/char/keyboard.c | 3 ++- drivers/md/md.c | 14 +++++++------- drivers/md/multipath.c | 3 ++- drivers/net/appletalk/cops_ffdrv.h | 2 +- drivers/net/appletalk/cops_ltdrv.h | 2 +- drivers/net/arcnet/capmode.c | 2 +- drivers/video/fbmem.c | 2 +- drivers/video/fbsysfs.c | 2 +- drivers/video/sis/init.c | 4 ++-- drivers/video/sis/init.h | 3 --- drivers/video/sis/init301.c | 9 +++++---- drivers/video/sis/init301.h | 4 ---- drivers/video/sis/sis_main.c | 5 +++-- fs/bad_inode.c | 2 +- fs/buffer.c | 2 +- fs/char_dev.c | 2 +- fs/dcache.c | 2 +- fs/eventpoll.c | 2 +- fs/exec.c | 3 ++- fs/jffs2/compr_rubin.c | 18 ++++++++++++------ fs/jffs2/compr_zlib.c | 12 ++++++++---- fs/locks.c | 6 +++--- fs/mbcache.c | 2 +- fs/mpage.c | 2 +- fs/namei.c | 8 ++++---- fs/nfs/idmap.c | 4 ++-- fs/nfs/inode.c | 4 ++-- fs/nls/nls_base.c | 2 +- fs/select.c | 6 ++++-- include/asm-i386/floppy.h | 2 +- include/asm-parisc/floppy.h | 2 +- include/asm-sh/floppy.h | 2 +- include/asm-x86_64/floppy.h | 2 +- include/linux/binfmts.h | 1 - 38 files changed, 93 insertions(+), 86 deletions(-) (limited to 'fs') diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 145c1fbffe01..f8a8b68dced0 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -74,7 +74,7 @@ static struct request_queue *rd_queue[CONFIG_BLK_DEV_RAM_COUNT]; * architecture-specific setup routine (from the stored boot sector * information). */ -int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ +static int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ /* * It would be very desirable to have a soft-blocksize (that in the case * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 647a71b12a2a..ac96de15d833 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -292,7 +292,7 @@ module_param(cdu31a_irq, int, 0); /* The interrupt handler will wake this queue up when it gets an interrupts. */ -DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait); +static DECLARE_WAIT_QUEUE_HEAD(cdu31a_irq_wait); static int irq_flag = 0; static int curr_control_reg = 0; /* Current value of the control register */ @@ -2947,7 +2947,7 @@ static int scd_block_media_changed(struct gendisk *disk) return cdrom_media_changed(&scd_info); } -struct block_device_operations scd_bdops = +static struct block_device_operations scd_bdops = { .owner = THIS_MODULE, .open = scd_block_open, @@ -3216,7 +3216,7 @@ errout3: } -void __exit cdu31a_exit(void) +static void __exit cdu31a_exit(void) { del_gendisk(scd_gendisk); put_disk(scd_gendisk); diff --git a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c index ccde7ab491d4..07bbd24e3c18 100644 --- a/drivers/cdrom/mcdx.c +++ b/drivers/cdrom/mcdx.c @@ -107,20 +107,20 @@ static const char *mcdx_c_version The _direct_ size is the number of sectors we're allowed to skip directly (performing a read instead of requesting the new sector needed */ -const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */ -const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */ +static const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */ +static const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */ enum drivemodes { TOC, DATA, RAW, COOKED }; enum datamodes { MODE0, MODE1, MODE2 }; enum resetmodes { SOFT, HARD }; -const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ -const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ -const int DOOR = 0x04; /* door locking capability */ -const int MULTI = 0x08; /* multi session capability */ +static const int SINGLE = 0x01; /* single speed drive (FX001S, LU) */ +static const int DOUBLE = 0x02; /* double speed drive (FX001D, ..? */ +static const int DOOR = 0x04; /* door locking capability */ +static const int MULTI = 0x08; /* multi session capability */ -const unsigned char READ1X = 0xc0; -const unsigned char READ2X = 0xc1; +static const unsigned char READ1X = 0xc0; +static const unsigned char READ2X = 0xc1; /* DECLARATIONS ****************************************************/ @@ -210,9 +210,7 @@ struct s_drive_stuff { repeated here to show what's going on. And to sense, if they're changed elsewhere. */ -/* declared in blk.h */ -int mcdx_init(void); -void do_mcdx_request(request_queue_t * q); +static int mcdx_init(void); static int mcdx_block_open(struct inode *inode, struct file *file) { @@ -569,7 +567,7 @@ static int mcdx_audio_ioctl(struct cdrom_device_info *cdi, } } -void do_mcdx_request(request_queue_t * q) +static void do_mcdx_request(request_queue_t * q) { struct s_drive_stuff *stuffp; struct request *req; @@ -1028,7 +1026,7 @@ int __mcdx_init(void) return 0; } -void __exit mcdx_exit(void) +static void __exit mcdx_exit(void) { int i; @@ -1075,7 +1073,7 @@ module_exit(mcdx_exit); /* Support functions ************************************************/ -int __init mcdx_init_drive(int drive) +static int __init mcdx_init_drive(int drive) { struct s_version version; struct gendisk *disk; @@ -1261,7 +1259,7 @@ int __init mcdx_init_drive(int drive) return 0; } -int __init mcdx_init(void) +static int __init mcdx_init(void) { int drive; xwarn("Version 2.14(hs) \n"); diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index fc2c433f6a29..452d34675159 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -5895,7 +5895,7 @@ int __init sbpcd_init(void) } /*==========================================================================*/ #ifdef MODULE -void sbpcd_exit(void) +static void sbpcd_exit(void) { int j; diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 3ce51c6a1b18..7b19e02f112f 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -1026,7 +1026,8 @@ static void kbd_rawcode(unsigned char data) put_queue(vc, data); } -void kbd_keycode(unsigned int keycode, int down, int hw_raw, struct pt_regs *regs) +static void kbd_keycode(unsigned int keycode, int down, + int hw_raw, struct pt_regs *regs) { struct vc_data *vc = vc_cons[fg_console].d; unsigned short keysym, *key_map; diff --git a/drivers/md/md.c b/drivers/md/md.c index 97af857d8a88..d899204d3743 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -957,7 +957,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) } -struct super_type super_types[] = { +static struct super_type super_types[] = { [0] = { .name = "0.90.0", .owner = THIS_MODULE, @@ -2740,7 +2740,7 @@ static struct block_device_operations md_fops = .revalidate_disk= md_revalidate, }; -int md_thread(void * arg) +static int md_thread(void * arg) { mdk_thread_t *thread = arg; @@ -3232,7 +3232,7 @@ void md_handle_safemode(mddev_t *mddev) } -DECLARE_WAIT_QUEUE_HEAD(resync_wait); +static DECLARE_WAIT_QUEUE_HEAD(resync_wait); #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) @@ -3575,8 +3575,8 @@ void md_check_recovery(mddev_t *mddev) } } -int md_notify_reboot(struct notifier_block *this, - unsigned long code, void *x) +static int md_notify_reboot(struct notifier_block *this, + unsigned long code, void *x) { struct list_head *tmp; mddev_t *mddev; @@ -3599,7 +3599,7 @@ int md_notify_reboot(struct notifier_block *this, return NOTIFY_DONE; } -struct notifier_block md_notifier = { +static struct notifier_block md_notifier = { .notifier_call = md_notify_reboot, .next = NULL, .priority = INT_MAX, /* before any real devices */ @@ -3616,7 +3616,7 @@ static void md_geninit(void) p->proc_fops = &md_seq_fops; } -int __init md_init(void) +static int __init md_init(void) { int minor; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 1891e4930dcc..4e4bfde3db5d 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -103,7 +103,8 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err) mempool_free(mp_bh, conf->pool); } -int multipath_end_request(struct bio *bio, unsigned int bytes_done, int error) +static int multipath_end_request(struct bio *bio, unsigned int bytes_done, + int error) { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); diff --git a/drivers/net/appletalk/cops_ffdrv.h b/drivers/net/appletalk/cops_ffdrv.h index 4131b4a7a65b..31cf8c9c947f 100644 --- a/drivers/net/appletalk/cops_ffdrv.h +++ b/drivers/net/appletalk/cops_ffdrv.h @@ -28,7 +28,7 @@ #ifdef CONFIG_COPS_DAYNA -unsigned char ffdrv_code[] = { +static const unsigned char ffdrv_code[] = { 58,3,0,50,228,149,33,255,255,34,226,149, 249,17,40,152,33,202,154,183,237,82,77,68, 11,107,98,19,54,0,237,176,175,50,80,0, diff --git a/drivers/net/appletalk/cops_ltdrv.h b/drivers/net/appletalk/cops_ltdrv.h index 05de66dd9206..4afb8e18ba65 100644 --- a/drivers/net/appletalk/cops_ltdrv.h +++ b/drivers/net/appletalk/cops_ltdrv.h @@ -27,7 +27,7 @@ #ifdef CONFIG_COPS_TANGENT -unsigned char ltdrv_code[] = { +static const unsigned char ltdrv_code[] = { 58,3,0,50,148,10,33,143,15,62,85,119, 190,32,9,62,170,119,190,32,3,35,24,241, 34,146,10,249,17,150,10,33,143,15,183,237, diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c index 16e155b04129..66485585ab39 100644 --- a/drivers/net/arcnet/capmode.c +++ b/drivers/net/arcnet/capmode.c @@ -48,7 +48,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length, static int ack_tx(struct net_device *dev, int acked); -struct ArcProto capmode_proto = +static struct ArcProto capmode_proto = { 'r', XMTU, diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 208a68ceb63b..7705070191d9 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1312,7 +1312,7 @@ int fb_get_options(char *name, char **option) * Returns zero. * */ -int __init video_setup(char *options) +static int __init video_setup(char *options) { int i, global = 0; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 2bdda4010b81..c78a2c5961d3 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -354,7 +354,7 @@ static ssize_t show_pan(struct class_device *class_device, char *buf) fb_info->var.xoffset); } -struct class_device_attribute class_device_attrs[] = { +static struct class_device_attribute class_device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), __ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap), diff --git a/drivers/video/sis/init.c b/drivers/video/sis/init.c index 1994054d45ff..ecfd72178dbb 100644 --- a/drivers/video/sis/init.c +++ b/drivers/video/sis/init.c @@ -1384,7 +1384,7 @@ SiSInitPCIetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) /* HELPER: SetLVDSetc */ /*********************************************/ -void +static void SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { USHORT temp; @@ -1625,7 +1625,7 @@ SiS_ResetSegmentRegisters(SiS_Private *SiS_Pr,PSIS_HW_INFO HwInfo) /* HELPER: GetVBType */ /*********************************************/ -void +static void SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { USHORT flag=0, rev=0, nolcd=0, p4_0f, p4_25, p4_27; diff --git a/drivers/video/sis/init.h b/drivers/video/sis/init.h index 35030d300431..7e36b7ac1470 100644 --- a/drivers/video/sis/init.h +++ b/drivers/video/sis/init.h @@ -2394,11 +2394,9 @@ void SiS_SetRegOR(SISIOADDRESS Port,USHORT Index, USHORT DataOR); void SiS_DisplayOn(SiS_Private *SiS_Pr); void SiS_DisplayOff(SiS_Private *SiS_Pr); void SiSRegInit(SiS_Private *SiS_Pr, SISIOADDRESS BaseAddr); -void SiSSetLVDSetc(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); BOOLEAN SiSDetermineROMLayout661(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); void SiS_SetEnableDstn(SiS_Private *SiS_Pr, int enable); void SiS_SetEnableFstn(SiS_Private *SiS_Pr, int enable); -void SiS_GetVBType(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); BOOLEAN SiS_SearchModeID(SiS_Private *SiS_Pr, USHORT *ModeNo, USHORT *ModeIdIndex); UCHAR SiS_GetModePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); USHORT SiS_GetColorDepth(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex); @@ -2444,7 +2442,6 @@ extern void SiS_GetLCDResInfo(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT Mod extern void SiS_SetYPbPr(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); extern void SiS_SetTVMode(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); extern void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); -extern void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); extern void SiS_DisableBridge(SiS_Private *, PSIS_HW_INFO); extern BOOLEAN SiS_SetCRT2Group(SiS_Private *, PSIS_HW_INFO, USHORT); extern USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, diff --git a/drivers/video/sis/init301.c b/drivers/video/sis/init301.c index 2bc5b8097910..274dacd54bb8 100644 --- a/drivers/video/sis/init301.c +++ b/drivers/video/sis/init301.c @@ -86,6 +86,7 @@ #define SiS_I2CDELAYSHORT 150 static USHORT SiS_GetBIOSLCDResInfo(SiS_Private *SiS_Pr); +static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx); /*********************************************/ /* HELPER: Lock/Unlock CRT2 */ @@ -100,7 +101,7 @@ SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) SiS_SetRegOR(SiS_Pr->SiS_Part1Port,0x24,0x01); } -void +static void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { if(HwInfo->jChipType >= SIS_315H) @@ -4236,7 +4237,7 @@ SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) * from outside the context of a mode switch! * MUST call getVBType before calling this */ -void +static void SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo) { USHORT temp=0,tempah; @@ -9219,7 +9220,7 @@ SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) SiS_SetChReg(SiS_Pr, tempbx, 0); } -void +static void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx) { if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) @@ -9323,7 +9324,7 @@ SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempbx) /* Read from Chrontel 70xx */ /* Parameter is [Register no (S7-S0)] */ -USHORT +static USHORT SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempbx) { if(SiS_Pr->SiS_IF_DEF_CH70xx == 1) diff --git a/drivers/video/sis/init301.h b/drivers/video/sis/init301.h index f05aebc994b4..f84eb54164a5 100644 --- a/drivers/video/sis/init301.h +++ b/drivers/video/sis/init301.h @@ -293,7 +293,6 @@ static UCHAR SiS300_TrumpionData[7][80] = { #endif void SiS_UnLockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); -void SiS_LockCRT2(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); void SiS_EnableCRT2(SiS_Private *SiS_Pr); USHORT SiS_GetRatePtr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, PSIS_HW_INFO HwInfo); void SiS_WaitRetrace1(SiS_Private *SiS_Pr); @@ -310,7 +309,6 @@ USHORT SiS_GetVCLK2Ptr(SiS_Private *SiS_Pr, USHORT ModeNo, USHORT ModeIdIndex, USHORT RefreshRateTableIndex, PSIS_HW_INFO HwInfo); USHORT SiS_GetResInfo(SiS_Private *SiS_Pr,USHORT ModeNo,USHORT ModeIdIndex); void SiS_DisableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); -void SiS_EnableBridge(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); BOOLEAN SiS_SetCRT2Group(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo, USHORT ModeNo); void SiS_SiS30xBLOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); void SiS_SiS30xBLOff(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); @@ -319,8 +317,6 @@ void SiS_SetCH700x(SiS_Private *SiS_Pr, USHORT tempax); USHORT SiS_GetCH700x(SiS_Private *SiS_Pr, USHORT tempax); void SiS_SetCH701x(SiS_Private *SiS_Pr, USHORT tempax); USHORT SiS_GetCH701x(SiS_Private *SiS_Pr, USHORT tempax); -void SiS_SetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); -USHORT SiS_GetCH70xx(SiS_Private *SiS_Pr, USHORT tempax); void SiS_SetCH70xxANDOR(SiS_Private *SiS_Pr, USHORT tempax,USHORT tempbh); #ifdef SIS315H static void SiS_Chrontel701xOn(SiS_Private *SiS_Pr, PSIS_HW_INFO HwInfo); diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index b773c98f6513..698266036819 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -4762,7 +4762,8 @@ static void __devinit sisfb_post_sis315330(struct pci_dev *pdev) #endif -int __devinit sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit sisfb_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { struct sisfb_chip_info *chipinfo = &sisfb_chip_info[ent->driver_data]; struct sis_video_info *ivideo = NULL; @@ -5940,7 +5941,7 @@ MODULE_PARM_DESC(videoram, #endif #endif -int __devinit sisfb_init_module(void) +static int __devinit sisfb_init_module(void) { sisfb_setdefaultparms(); diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 672a31924f3c..e172180a1d8c 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c @@ -47,7 +47,7 @@ static struct file_operations bad_file_ops = .get_unmapped_area = EIO_ERROR, }; -struct inode_operations bad_inode_ops = +static struct inode_operations bad_inode_ops = { .create = EIO_ERROR, .lookup = EIO_ERROR, diff --git a/fs/buffer.c b/fs/buffer.c index 91ace8034bf7..6f88dcc6d002 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1210,7 +1210,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) return 1; } -struct buffer_head * +static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { /* Size must be multiple of hard sectorsize */ diff --git a/fs/char_dev.c b/fs/char_dev.c index a745b1d9e545..c1e3537909fc 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -328,7 +328,7 @@ void cd_forget(struct inode *inode) spin_unlock(&cdev_lock); } -void cdev_purge(struct cdev *cdev) +static void cdev_purge(struct cdev *cdev) { spin_lock(&cdev_lock); while (!list_empty(&cdev->list)) { diff --git a/fs/dcache.c b/fs/dcache.c index 496a4e08369c..3aa8a7e980d8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -39,7 +39,7 @@ int sysctl_vfs_cache_pressure = 100; EXPORT_SYMBOL_GPL(sysctl_vfs_cache_pressure); __cacheline_aligned_in_smp DEFINE_SPINLOCK(dcache_lock); -seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED; +static seqlock_t rename_lock __cacheline_aligned_in_smp = SEQLOCK_UNLOCKED; EXPORT_SYMBOL(dcache_lock); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 05b966cd6f76..9900e333655a 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -320,7 +320,7 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, /* * This semaphore is used to serialize ep_free() and eventpoll_release_file(). */ -struct semaphore epsem; +static struct semaphore epsem; /* Safe wake up implementation */ static struct poll_safewake psw; diff --git a/fs/exec.c b/fs/exec.c index a8394499926c..52acff3f44f0 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -197,7 +197,8 @@ static int count(char __user * __user * argv, int max) * memory to free pages in kernel mem. These are in a format ready * to be put directly into the top of new user memory. */ -int copy_strings(int argc,char __user * __user * argv, struct linux_binprm *bprm) +static int copy_strings(int argc, char __user * __user * argv, + struct linux_binprm *bprm) { struct page *kmapped_page = NULL; char *kaddr = NULL; diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 450d6624181f..09422388fb96 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -228,8 +228,10 @@ int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); } #endif -int jffs2_dynrubin_compress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, void *model) +static int jffs2_dynrubin_compress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t *sourcelen, uint32_t *dstlen, + void *model) { int bits[8]; unsigned char histo[256]; @@ -306,15 +308,19 @@ static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata } -int jffs2_rubinmips_decompress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t sourcelen, uint32_t dstlen, void *model) +static int jffs2_rubinmips_decompress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t sourcelen, uint32_t dstlen, + void *model) { rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); return 0; } -int jffs2_dynrubin_decompress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t sourcelen, uint32_t dstlen, void *model) +static int jffs2_dynrubin_decompress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t sourcelen, uint32_t dstlen, + void *model) { int bits[8]; int c; diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 9f9932c22adb..078a30e406b5 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -69,8 +69,10 @@ static void free_workspaces(void) #define free_workspaces() do { } while(0) #endif /* __KERNEL__ */ -int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t *sourcelen, uint32_t *dstlen, void *model) +static int jffs2_zlib_compress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t *sourcelen, uint32_t *dstlen, + void *model) { int ret; @@ -135,8 +137,10 @@ int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, return ret; } -int jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, - uint32_t srclen, uint32_t destlen, void *model) +static int jffs2_zlib_decompress(unsigned char *data_in, + unsigned char *cpage_out, + uint32_t srclen, uint32_t destlen, + void *model) { int ret; int wbits = MAX_WBITS; diff --git a/fs/locks.c b/fs/locks.c index 1792ce547af7..3fa6a7ce57a7 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -406,12 +406,12 @@ static void lease_release_private_callback(struct file_lock *fl) fl->fl_file->f_owner.signum = 0; } -int lease_mylease_callback(struct file_lock *fl, struct file_lock *try) +static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try) { return fl->fl_file == try->fl_file; } -struct lock_manager_operations lease_manager_ops = { +static struct lock_manager_operations lease_manager_ops = { .fl_break = lease_break_callback, .fl_release_private = lease_release_private_callback, .fl_mylease = lease_mylease_callback, @@ -1274,7 +1274,7 @@ int fcntl_getlease(struct file *filp) * * Called with kernel lock held. */ -int __setlease(struct file *filp, long arg, struct file_lock **flp) +static int __setlease(struct file *filp, long arg, struct file_lock **flp) { struct file_lock *fl, **before, **my_before = NULL, *lease = *flp; struct dentry *dentry = filp->f_dentry; diff --git a/fs/mbcache.c b/fs/mbcache.c index f9e4d2700cd8..c7170b9221a3 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -57,7 +57,7 @@ #define MB_CACHE_WRITER ((unsigned short)~0U >> 1) -DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue); +static DECLARE_WAIT_QUEUE_HEAD(mb_cache_queue); MODULE_AUTHOR("Andreas Gruenbacher "); MODULE_DESCRIPTION("Meta block cache (for extended attributes)"); diff --git a/fs/mpage.c b/fs/mpage.c index 68db5256a727..b92c0e64aefa 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -87,7 +87,7 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err) return 0; } -struct bio *mpage_bio_submit(int rw, struct bio *bio) +static struct bio *mpage_bio_submit(int rw, struct bio *bio) { bio->bi_end_io = mpage_end_io_read; if (rw == WRITE) diff --git a/fs/namei.c b/fs/namei.c index 0f76fd75591b..defe6781e003 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2071,8 +2071,8 @@ exit: * ->i_sem on parents, which works but leads to some truely excessive * locking]. */ -int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { int error = 0; struct inode *target; @@ -2116,8 +2116,8 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry, return error; } -int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) +static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) { struct inode *target; int error; diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b74c4e3a64e2..87f4f9aeac86 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -79,7 +79,7 @@ static ssize_t idmap_pipe_upcall(struct file *, struct rpc_pipe_msg *, char __user *, size_t); static ssize_t idmap_pipe_downcall(struct file *, const char __user *, size_t); -void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); +static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); static unsigned int fnvhash32(const void *, size_t); @@ -434,7 +434,7 @@ out: return ret; } -void +static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) { struct idmap_msg *im = msg->data; diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6345f26e87ee..f2317f3e29f9 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1904,7 +1904,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) } } -int nfs_init_inodecache(void) +static int nfs_init_inodecache(void) { nfs_inode_cachep = kmem_cache_create("nfs_inode_cache", sizeof(struct nfs_inode), @@ -1916,7 +1916,7 @@ int nfs_init_inodecache(void) return 0; } -void nfs_destroy_inodecache(void) +static void nfs_destroy_inodecache(void) { if (kmem_cache_destroy(nfs_inode_cachep)) printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); diff --git a/fs/nls/nls_base.c b/fs/nls/nls_base.c index 897512796edb..a912debcd20b 100644 --- a/fs/nls/nls_base.c +++ b/fs/nls/nls_base.c @@ -243,7 +243,7 @@ void unload_nls(struct nls_table *nls) module_put(nls->owner); } -wchar_t charset2uni[256] = { +static wchar_t charset2uni[256] = { /* 0x00*/ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, diff --git a/fs/select.c b/fs/select.c index 25b1ccac2f2c..b80e7eb0ac0d 100644 --- a/fs/select.c +++ b/fs/select.c @@ -55,7 +55,8 @@ struct poll_table_page { * as all select/poll functions have to call it to add an entry to the * poll table. */ -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p); +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table *p); void poll_initwait(struct poll_wqueues *pwq) { @@ -87,7 +88,8 @@ void poll_freewait(struct poll_wqueues *pwq) EXPORT_SYMBOL(poll_freewait); -void __pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *_p) +static void __pollwait(struct file *filp, wait_queue_head_t *wait_address, + poll_table *_p) { struct poll_wqueues *p = container_of(_p, struct poll_wqueues, pt); struct poll_table_page *table = p->table; diff --git a/include/asm-i386/floppy.h b/include/asm-i386/floppy.h index f4782284807a..79727afb94c9 100644 --- a/include/asm-i386/floppy.h +++ b/include/asm-i386/floppy.h @@ -257,7 +257,7 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) return 0; } -struct fd_routine_l { +static struct fd_routine_l { int (*_request_dma)(unsigned int dmanr, const char * device_id); void (*_free_dma)(unsigned int dmanr); int (*_get_dma_residue)(unsigned int dummy); diff --git a/include/asm-parisc/floppy.h b/include/asm-parisc/floppy.h index 47f53df2cef5..ca3aed768cdc 100644 --- a/include/asm-parisc/floppy.h +++ b/include/asm-parisc/floppy.h @@ -235,7 +235,7 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) return 0; } -struct fd_routine_l { +static struct fd_routine_l { int (*_request_dma)(unsigned int dmanr, const char * device_id); void (*_free_dma)(unsigned int dmanr); int (*_get_dma_residue)(unsigned int dummy); diff --git a/include/asm-sh/floppy.h b/include/asm-sh/floppy.h index f030ca08052b..38d7a2942476 100644 --- a/include/asm-sh/floppy.h +++ b/include/asm-sh/floppy.h @@ -227,7 +227,7 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) return 0; } -struct fd_routine_l { +static struct fd_routine_l { int (*_request_dma)(unsigned int dmanr, const char * device_id); void (*_free_dma)(unsigned int dmanr); int (*_get_dma_residue)(unsigned int dummy); diff --git a/include/asm-x86_64/floppy.h b/include/asm-x86_64/floppy.h index bca9b28a1a0a..af7ded63b517 100644 --- a/include/asm-x86_64/floppy.h +++ b/include/asm-x86_64/floppy.h @@ -223,7 +223,7 @@ static int hard_dma_setup(char *addr, unsigned long size, int mode, int io) return 0; } -struct fd_routine_l { +static struct fd_routine_l { int (*_request_dma)(unsigned int dmanr, const char * device_id); void (*_free_dma)(unsigned int dmanr); int (*_get_dma_residue)(unsigned int dummy); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 54f820832c73..7e736e201c46 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -77,7 +77,6 @@ extern int flush_old_exec(struct linux_binprm * bprm); extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); -extern int copy_strings(int argc,char __user * __user * argv,struct linux_binprm *bprm); extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm); extern void compute_creds(struct linux_binprm *binprm); extern int do_coredump(long signr, int exit_code, struct pt_regs * regs); -- cgit v1.2.3 From 291c4a75ce7632ee5c565359fb875ba0597f76be Mon Sep 17 00:00:00 2001 From: "Randy.Dunlap" Date: Thu, 5 May 2005 16:16:11 -0700 Subject: [PATCH] reiserfs: use NULL instead of 0 Use NULL instead of 0 for pointer (sparse warning): fs/reiserfs/namei.c:611:50: warning: Using plain integer as NULL pointer Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/reiserfs/namei.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 80e92d9b81cb..7d4dc5f5aa8b 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -608,7 +608,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, goto out_failed; } - retval = reiserfs_new_inode (&th, dir, mode, 0, 0/*i_size*/, dentry, inode); + retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode); if (retval) goto out_failed; -- cgit v1.2.3 From 3677209239ed71d2654e73eecfab1dbec2af11a9 Mon Sep 17 00:00:00 2001 From: Paolo 'Blaisorblade' Giarrusso Date: Thu, 5 May 2005 16:16:12 -0700 Subject: [PATCH] comments on locking of task->comm Add some comments about task->comm, to explain what it is near its definition and provide some important pointers to its uses. Signed-off-by: Paolo 'Blaisorblade' Giarrusso Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 4 +++- include/linux/sched.h | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/exec.c b/fs/exec.c index 52acff3f44f0..e56ee2437025 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -869,9 +869,11 @@ int flush_old_exec(struct linux_binprm * bprm) if (current->euid == current->uid && current->egid == current->gid) current->mm->dumpable = 1; name = bprm->filename; + + /* Copies the binary name from after last slash */ for (i=0; (ch = *(name++)) != '\0';) { if (ch == '/') - i = 0; + i = 0; /* overwrite what we wrote */ else if (i < (sizeof(tcomm) - 1)) tcomm[i++] = ch; diff --git a/include/linux/sched.h b/include/linux/sched.h index 5f868a588581..4dbb109022f3 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -578,7 +578,7 @@ struct task_struct { unsigned long flags; /* per process flags, defined below */ unsigned long ptrace; - int lock_depth; /* Lock depth */ + int lock_depth; /* BKL lock depth */ int prio, static_prio; struct list_head run_list; @@ -661,7 +661,10 @@ struct task_struct { struct key *thread_keyring; /* keyring private to this thread */ #endif int oomkilladj; /* OOM kill score adjustment (bit shift). */ - char comm[TASK_COMM_LEN]; + char comm[TASK_COMM_LEN]; /* executable name excluding path + - access with [gs]et_task_comm (which lock + it with task_lock()) + - initialized normally by flush_old_exec */ /* file system info */ int link_count, total_link_count; /* ipc stuff */ -- cgit v1.2.3 From f59154c53fac0bfee52393247beadf0474770351 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Thu, 5 May 2005 16:16:21 -0700 Subject: [PATCH] fs/udf/udftime.c: fix off by one error This patch fixes an off by one error found by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/udf/udftime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index c2634bda6b50..457a8fe28575 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -103,7 +103,7 @@ udf_stamp_to_time(time_t *dest, long *dest_usec, kernel_timestamp src) offset = 0; if ((src.year < EPOCH_YEAR) || - (src.year > EPOCH_YEAR+MAX_YEAR_SECONDS)) + (src.year >= EPOCH_YEAR+MAX_YEAR_SECONDS)) { *dest = -1; *dest_usec = -1; -- cgit v1.2.3 From b2411dd202e854d1f3be541135af8bb9872ea8b6 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 6 May 2005 17:41:01 -0700 Subject: [PATCH] revert msdos partitioning fix This change from March 3rd causes the partition parsing code to ignore partitions which have a signature byte of zero. Turns out that more people have such partitions than we expected, and their device numbering is coming up wrong in post-2.6.11 kernels. So revert the change while we think about the problem a bit more. Cc: Andries Brouwer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/partitions/msdos.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'fs') diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 17ee1b4ff087..584a27b2bbd5 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -114,9 +114,6 @@ parse_extended(struct parsed_partitions *state, struct block_device *bdev, */ for (i=0; i<4; i++, p++) { u32 offs, size, next; - - if (SYS_IND(p) == 0) - continue; if (!NR_SECTS(p) || is_extended_partition(p)) continue; @@ -433,8 +430,6 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) for (slot = 1 ; slot <= 4 ; slot++, p++) { u32 start = START_SECT(p)*sector_size; u32 size = NR_SECTS(p)*sector_size; - if (SYS_IND(p) == 0) - continue; if (!size) continue; if (is_extended_partition(p)) { -- cgit v1.2.3