]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.20.2/ufs-restore-back-support-of-openstep.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 2.6.20.2 / ufs-restore-back-support-of-openstep.patch
1 From stable-bounces@linux.kernel.org Thu Feb 8 14:21:58 2007
2 From: Evgeniy Dushistov <dushistov@mail.ru>
3 Date: Thu, 08 Feb 2007 14:20:25 -0800
4 Subject: ufs: restore back support of openstep
5 To: torvalds@linux-foundation.org
6 Cc: akpm@linux-foundation.org, dushistov@mail.ru, stable@kernel.org
7 Message-ID: <200702082220.l18MKQcn028473@shell0.pdx.osdl.net>
8
9
10 From: Evgeniy Dushistov <dushistov@mail.ru>
11
12 This is a fix of regression, which triggered by ~2.6.16.
13
14 Patch with name ufs-directory-and-page-cache-from-blocks-to-pages.patch: in
15 additional to conversation from block to page cache mechanism added new
16 checks of directory integrity, one of them that directory entry do not
17 across directory chunks.
18
19 But some kinds of UFS: OpenStep UFS and Apple UFS (looks like these are the
20 same filesystems) have different directory chunk size, then common
21 UFSes(BSD and Solaris UFS).
22
23 So this patch adds ability to works with variable size of directory chunks,
24 and set it for ufstype=openstep to right size.
25
26 Tested on darwin ufs.
27
28 Signed-off-by: Evgeniy Dushistov <dushistov@mail.ru>
29 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
30 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
31
32 ---
33 fs/ufs/dir.c | 21 ++++++++++++---------
34 fs/ufs/super.c | 5 ++++-
35 include/linux/ufs_fs.h | 1 +
36 3 files changed, 17 insertions(+), 10 deletions(-)
37
38 --- linux-2.6.20.1.orig/fs/ufs/dir.c
39 +++ linux-2.6.20.1/fs/ufs/dir.c
40 @@ -106,12 +106,13 @@ static void ufs_check_page(struct page *
41 char *kaddr = page_address(page);
42 unsigned offs, rec_len;
43 unsigned limit = PAGE_CACHE_SIZE;
44 + const unsigned chunk_mask = UFS_SB(sb)->s_uspi->s_dirblksize - 1;
45 struct ufs_dir_entry *p;
46 char *error;
47
48 if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) {
49 limit = dir->i_size & ~PAGE_CACHE_MASK;
50 - if (limit & (UFS_SECTOR_SIZE - 1))
51 + if (limit & chunk_mask)
52 goto Ebadsize;
53 if (!limit)
54 goto out;
55 @@ -126,7 +127,7 @@ static void ufs_check_page(struct page *
56 goto Ealign;
57 if (rec_len < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, p)))
58 goto Enamelen;
59 - if (((offs + rec_len - 1) ^ offs) & ~(UFS_SECTOR_SIZE-1))
60 + if (((offs + rec_len - 1) ^ offs) & ~chunk_mask)
61 goto Espan;
62 if (fs32_to_cpu(sb, p->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
63 UFS_SB(sb)->s_uspi->s_ncg))
64 @@ -310,6 +311,7 @@ int ufs_add_link(struct dentry *dentry,
65 int namelen = dentry->d_name.len;
66 struct super_block *sb = dir->i_sb;
67 unsigned reclen = UFS_DIR_REC_LEN(namelen);
68 + const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
69 unsigned short rec_len, name_len;
70 struct page *page = NULL;
71 struct ufs_dir_entry *de;
72 @@ -342,8 +344,8 @@ int ufs_add_link(struct dentry *dentry,
73 if ((char *)de == dir_end) {
74 /* We hit i_size */
75 name_len = 0;
76 - rec_len = UFS_SECTOR_SIZE;
77 - de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
78 + rec_len = chunk_size;
79 + de->d_reclen = cpu_to_fs16(sb, chunk_size);
80 de->d_ino = 0;
81 goto got_it;
82 }
83 @@ -431,7 +433,7 @@ ufs_readdir(struct file *filp, void *dir
84 unsigned int offset = pos & ~PAGE_CACHE_MASK;
85 unsigned long n = pos >> PAGE_CACHE_SHIFT;
86 unsigned long npages = ufs_dir_pages(inode);
87 - unsigned chunk_mask = ~(UFS_SECTOR_SIZE - 1);
88 + unsigned chunk_mask = ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
89 int need_revalidate = filp->f_version != inode->i_version;
90 unsigned flags = UFS_SB(sb)->s_flags;
91
92 @@ -511,7 +513,7 @@ int ufs_delete_entry(struct inode *inode
93 struct super_block *sb = inode->i_sb;
94 struct address_space *mapping = page->mapping;
95 char *kaddr = page_address(page);
96 - unsigned from = ((char*)dir - kaddr) & ~(UFS_SECTOR_SIZE - 1);
97 + unsigned from = ((char*)dir - kaddr) & ~(UFS_SB(sb)->s_uspi->s_dirblksize - 1);
98 unsigned to = ((char*)dir - kaddr) + fs16_to_cpu(sb, dir->d_reclen);
99 struct ufs_dir_entry *pde = NULL;
100 struct ufs_dir_entry *de = (struct ufs_dir_entry *) (kaddr + from);
101 @@ -556,6 +558,7 @@ int ufs_make_empty(struct inode * inode,
102 struct super_block * sb = dir->i_sb;
103 struct address_space *mapping = inode->i_mapping;
104 struct page *page = grab_cache_page(mapping, 0);
105 + const unsigned int chunk_size = UFS_SB(sb)->s_uspi->s_dirblksize;
106 struct ufs_dir_entry * de;
107 char *base;
108 int err;
109 @@ -563,7 +566,7 @@ int ufs_make_empty(struct inode * inode,
110 if (!page)
111 return -ENOMEM;
112 kmap(page);
113 - err = mapping->a_ops->prepare_write(NULL, page, 0, UFS_SECTOR_SIZE);
114 + err = mapping->a_ops->prepare_write(NULL, page, 0, chunk_size);
115 if (err) {
116 unlock_page(page);
117 goto fail;
118 @@ -584,11 +587,11 @@ int ufs_make_empty(struct inode * inode,
119 ((char *)de + fs16_to_cpu(sb, de->d_reclen));
120 de->d_ino = cpu_to_fs32(sb, dir->i_ino);
121 ufs_set_de_type(sb, de, dir->i_mode);
122 - de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
123 + de->d_reclen = cpu_to_fs16(sb, chunk_size - UFS_DIR_REC_LEN(1));
124 ufs_set_de_namlen(sb, de, 2);
125 strcpy (de->d_name, "..");
126
127 - err = ufs_commit_chunk(page, 0, UFS_SECTOR_SIZE);
128 + err = ufs_commit_chunk(page, 0, chunk_size);
129 fail:
130 kunmap(page);
131 page_cache_release(page);
132 --- linux-2.6.20.1.orig/fs/ufs/super.c
133 +++ linux-2.6.20.1/fs/ufs/super.c
134 @@ -649,7 +649,7 @@ static int ufs_fill_super(struct super_b
135 kmalloc (sizeof(struct ufs_sb_private_info), GFP_KERNEL);
136 if (!uspi)
137 goto failed;
138 -
139 + uspi->s_dirblksize = UFS_SECTOR_SIZE;
140 super_block_offset=UFS_SBLOCK;
141
142 /* Keep 2Gig file limit. Some UFS variants need to override
143 @@ -718,6 +718,7 @@ static int ufs_fill_super(struct super_b
144 break;
145
146 case UFS_MOUNT_UFSTYPE_NEXTSTEP:
147 + /*TODO: check may be we need set special dir block size?*/
148 UFSD("ufstype=nextstep\n");
149 uspi->s_fsize = block_size = 1024;
150 uspi->s_fmask = ~(1024 - 1);
151 @@ -733,6 +734,7 @@ static int ufs_fill_super(struct super_b
152 break;
153
154 case UFS_MOUNT_UFSTYPE_NEXTSTEP_CD:
155 + /*TODO: check may be we need set special dir block size?*/
156 UFSD("ufstype=nextstep-cd\n");
157 uspi->s_fsize = block_size = 2048;
158 uspi->s_fmask = ~(2048 - 1);
159 @@ -754,6 +756,7 @@ static int ufs_fill_super(struct super_b
160 uspi->s_fshift = 10;
161 uspi->s_sbsize = super_block_size = 2048;
162 uspi->s_sbbase = 0;
163 + uspi->s_dirblksize = 1024;
164 flags |= UFS_DE_44BSD | UFS_UID_44BSD | UFS_ST_44BSD | UFS_CG_44BSD;
165 if (!(sb->s_flags & MS_RDONLY)) {
166 if (!silent)
167 --- linux-2.6.20.1.orig/include/linux/ufs_fs.h
168 +++ linux-2.6.20.1/include/linux/ufs_fs.h
169 @@ -789,6 +789,7 @@ struct ufs_sb_private_info {
170
171 __u32 s_maxsymlinklen;/* upper limit on fast symlinks' size */
172 __s32 fs_magic; /* filesystem magic */
173 + unsigned int s_dirblksize;
174 };
175
176 /*