diff options
Diffstat (limited to 'fs/ext2/dir.c')
| -rw-r--r-- | fs/ext2/dir.c | 52 | 
1 files changed, 29 insertions, 23 deletions
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 2709b34206a..6e1d4ab09d7 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -28,21 +28,30 @@  typedef struct ext2_dir_entry_2 ext2_dirent; +/* + * Tests against MAX_REC_LEN etc were put in place for 64k block + * sizes; if that is not possible on this arch, we can skip + * those tests and speed things up. + */  static inline unsigned ext2_rec_len_from_disk(__le16 dlen)  {  	unsigned len = le16_to_cpu(dlen); +#if (PAGE_CACHE_SIZE >= 65536)  	if (len == EXT2_MAX_REC_LEN)  		return 1 << 16; +#endif  	return len;  }  static inline __le16 ext2_rec_len_to_disk(unsigned len)  { +#if (PAGE_CACHE_SIZE >= 65536)  	if (len == (1 << 16))  		return cpu_to_le16(EXT2_MAX_REC_LEN);  	else  		BUG_ON(len > (1 << 16)); +#endif  	return cpu_to_le16(len);  } @@ -129,15 +138,15 @@ static void ext2_check_page(struct page *page, int quiet)  		p = (ext2_dirent *)(kaddr + offs);  		rec_len = ext2_rec_len_from_disk(p->rec_len); -		if (rec_len < EXT2_DIR_REC_LEN(1)) +		if (unlikely(rec_len < EXT2_DIR_REC_LEN(1)))  			goto Eshort; -		if (rec_len & 3) +		if (unlikely(rec_len & 3))  			goto Ealign; -		if (rec_len < EXT2_DIR_REC_LEN(p->name_len)) +		if (unlikely(rec_len < EXT2_DIR_REC_LEN(p->name_len)))  			goto Enamelen; -		if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)) +		if (unlikely(((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)))  			goto Espan; -		if (le32_to_cpu(p->inode) > max_inumber) +		if (unlikely(le32_to_cpu(p->inode) > max_inumber))  			goto Einumber;  	}  	if (offs != limit) @@ -270,7 +279,7 @@ static unsigned char ext2_type_by_mode[S_IFMT >> S_SHIFT] = {  static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)  { -	mode_t mode = inode->i_mode; +	umode_t mode = inode->i_mode;  	if (EXT2_HAS_INCOMPAT_FEATURE(inode->i_sb, EXT2_FEATURE_INCOMPAT_FILETYPE))  		de->file_type = ext2_type_by_mode[(mode & S_IFMT)>>S_SHIFT];  	else @@ -278,17 +287,17 @@ static inline void ext2_set_de_type(ext2_dirent *de, struct inode *inode)  }  static int -ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) +ext2_readdir(struct file *file, struct dir_context *ctx)  { -	loff_t pos = filp->f_pos; -	struct inode *inode = filp->f_path.dentry->d_inode; +	loff_t pos = ctx->pos; +	struct inode *inode = file_inode(file);  	struct super_block *sb = inode->i_sb;  	unsigned int offset = pos & ~PAGE_CACHE_MASK;  	unsigned long n = pos >> PAGE_CACHE_SHIFT;  	unsigned long npages = dir_pages(inode);  	unsigned chunk_mask = ~(ext2_chunk_size(inode)-1);  	unsigned char *types = NULL; -	int need_revalidate = filp->f_version != inode->i_version; +	int need_revalidate = file->f_version != inode->i_version;  	if (pos > inode->i_size - EXT2_DIR_REC_LEN(1))  		return 0; @@ -305,16 +314,16 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)  			ext2_error(sb, __func__,  				   "bad page in #%lu",  				   inode->i_ino); -			filp->f_pos += PAGE_CACHE_SIZE - offset; +			ctx->pos += PAGE_CACHE_SIZE - offset;  			return PTR_ERR(page);  		}  		kaddr = page_address(page);  		if (unlikely(need_revalidate)) {  			if (offset) {  				offset = ext2_validate_entry(kaddr, offset, chunk_mask); -				filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; +				ctx->pos = (n<<PAGE_CACHE_SHIFT) + offset;  			} -			filp->f_version = inode->i_version; +			file->f_version = inode->i_version;  			need_revalidate = 0;  		}  		de = (ext2_dirent *)(kaddr+offset); @@ -327,22 +336,19 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir)  				return -EIO;  			}  			if (de->inode) { -				int over;  				unsigned char d_type = DT_UNKNOWN;  				if (types && de->file_type < EXT2_FT_MAX)  					d_type = types[de->file_type]; -				offset = (char *)de - kaddr; -				over = filldir(dirent, de->name, de->name_len, -						(n<<PAGE_CACHE_SHIFT) | offset, -						le32_to_cpu(de->inode), d_type); -				if (over) { +				if (!dir_emit(ctx, de->name, de->name_len, +						le32_to_cpu(de->inode), +						d_type)) {  					ext2_put_page(page);  					return 0;  				}  			} -			filp->f_pos += ext2_rec_len_from_disk(de->rec_len); +			ctx->pos += ext2_rec_len_from_disk(de->rec_len);  		}  		ext2_put_page(page);  	} @@ -636,7 +642,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)  		unlock_page(page);  		goto fail;  	} -	kaddr = kmap_atomic(page, KM_USER0); +	kaddr = kmap_atomic(page);  	memset(kaddr, 0, chunk_size);  	de = (struct ext2_dir_entry_2 *)kaddr;  	de->name_len = 1; @@ -651,7 +657,7 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)  	de->inode = cpu_to_le32(parent->i_ino);  	memcpy (de->name, "..\0", 4);  	ext2_set_de_type (de, inode); -	kunmap_atomic(kaddr, KM_USER0); +	kunmap_atomic(kaddr);  	err = ext2_commit_chunk(page, 0, chunk_size);  fail:  	page_cache_release(page); @@ -715,7 +721,7 @@ not_empty:  const struct file_operations ext2_dir_operations = {  	.llseek		= generic_file_llseek,  	.read		= generic_read_dir, -	.readdir	= ext2_readdir, +	.iterate	= ext2_readdir,  	.unlocked_ioctl = ext2_ioctl,  #ifdef CONFIG_COMPAT  	.compat_ioctl	= ext2_compat_ioctl,  | 
