Commit eab1df71a0ef6d333b9b826deaa0d0eb4b4f69dc
Committed by
Linus Torvalds
1 parent
5451f79f5f
Exists in
master
and in
7 other branches
iget: stop JFS from using iget() and read_inode()
Stop the JFS filesystem from using iget() and read_inode(). Replace jfs_read_inode() with jfs_iget(), and call that instead of iget(). jfs_iget() then uses iget_locked() directly and returns a proper error code instead of an inode in the event of an error. jfs_fill_super() returns any error incurred when getting the root inode instead of EINVAL. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 4 changed files with 40 additions and 31 deletions Inline Diff
fs/jfs/inode.c
1 | /* | 1 | /* |
2 | * Copyright (C) International Business Machines Corp., 2000-2004 | 2 | * Copyright (C) International Business Machines Corp., 2000-2004 |
3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 | 3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
13 | * the GNU General Public License for more details. | 13 | * the GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/mpage.h> | 21 | #include <linux/mpage.h> |
22 | #include <linux/buffer_head.h> | 22 | #include <linux/buffer_head.h> |
23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
24 | #include <linux/quotaops.h> | 24 | #include <linux/quotaops.h> |
25 | #include "jfs_incore.h" | 25 | #include "jfs_incore.h" |
26 | #include "jfs_inode.h" | 26 | #include "jfs_inode.h" |
27 | #include "jfs_filsys.h" | 27 | #include "jfs_filsys.h" |
28 | #include "jfs_imap.h" | 28 | #include "jfs_imap.h" |
29 | #include "jfs_extent.h" | 29 | #include "jfs_extent.h" |
30 | #include "jfs_unicode.h" | 30 | #include "jfs_unicode.h" |
31 | #include "jfs_debug.h" | 31 | #include "jfs_debug.h" |
32 | 32 | ||
33 | 33 | ||
34 | void jfs_read_inode(struct inode *inode) | 34 | struct inode *jfs_iget(struct super_block *sb, unsigned long ino) |
35 | { | 35 | { |
36 | if (diRead(inode)) { | 36 | struct inode *inode; |
37 | make_bad_inode(inode); | 37 | int ret; |
38 | return; | 38 | |
39 | inode = iget_locked(sb, ino); | ||
40 | if (!inode) | ||
41 | return ERR_PTR(-ENOMEM); | ||
42 | if (!(inode->i_state & I_NEW)) | ||
43 | return inode; | ||
44 | |||
45 | ret = diRead(inode); | ||
46 | if (ret < 0) { | ||
47 | iget_failed(inode); | ||
48 | return ERR_PTR(ret); | ||
39 | } | 49 | } |
40 | 50 | ||
41 | if (S_ISREG(inode->i_mode)) { | 51 | if (S_ISREG(inode->i_mode)) { |
42 | inode->i_op = &jfs_file_inode_operations; | 52 | inode->i_op = &jfs_file_inode_operations; |
43 | inode->i_fop = &jfs_file_operations; | 53 | inode->i_fop = &jfs_file_operations; |
44 | inode->i_mapping->a_ops = &jfs_aops; | 54 | inode->i_mapping->a_ops = &jfs_aops; |
45 | } else if (S_ISDIR(inode->i_mode)) { | 55 | } else if (S_ISDIR(inode->i_mode)) { |
46 | inode->i_op = &jfs_dir_inode_operations; | 56 | inode->i_op = &jfs_dir_inode_operations; |
47 | inode->i_fop = &jfs_dir_operations; | 57 | inode->i_fop = &jfs_dir_operations; |
48 | } else if (S_ISLNK(inode->i_mode)) { | 58 | } else if (S_ISLNK(inode->i_mode)) { |
49 | if (inode->i_size >= IDATASIZE) { | 59 | if (inode->i_size >= IDATASIZE) { |
50 | inode->i_op = &page_symlink_inode_operations; | 60 | inode->i_op = &page_symlink_inode_operations; |
51 | inode->i_mapping->a_ops = &jfs_aops; | 61 | inode->i_mapping->a_ops = &jfs_aops; |
52 | } else | 62 | } else |
53 | inode->i_op = &jfs_symlink_inode_operations; | 63 | inode->i_op = &jfs_symlink_inode_operations; |
54 | } else { | 64 | } else { |
55 | inode->i_op = &jfs_file_inode_operations; | 65 | inode->i_op = &jfs_file_inode_operations; |
56 | init_special_inode(inode, inode->i_mode, inode->i_rdev); | 66 | init_special_inode(inode, inode->i_mode, inode->i_rdev); |
57 | } | 67 | } |
68 | unlock_new_inode(inode); | ||
69 | return inode; | ||
58 | } | 70 | } |
59 | 71 | ||
60 | /* | 72 | /* |
61 | * Workhorse of both fsync & write_inode | 73 | * Workhorse of both fsync & write_inode |
62 | */ | 74 | */ |
63 | int jfs_commit_inode(struct inode *inode, int wait) | 75 | int jfs_commit_inode(struct inode *inode, int wait) |
64 | { | 76 | { |
65 | int rc = 0; | 77 | int rc = 0; |
66 | tid_t tid; | 78 | tid_t tid; |
67 | static int noisy = 5; | 79 | static int noisy = 5; |
68 | 80 | ||
69 | jfs_info("In jfs_commit_inode, inode = 0x%p", inode); | 81 | jfs_info("In jfs_commit_inode, inode = 0x%p", inode); |
70 | 82 | ||
71 | /* | 83 | /* |
72 | * Don't commit if inode has been committed since last being | 84 | * Don't commit if inode has been committed since last being |
73 | * marked dirty, or if it has been deleted. | 85 | * marked dirty, or if it has been deleted. |
74 | */ | 86 | */ |
75 | if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) | 87 | if (inode->i_nlink == 0 || !test_cflag(COMMIT_Dirty, inode)) |
76 | return 0; | 88 | return 0; |
77 | 89 | ||
78 | if (isReadOnly(inode)) { | 90 | if (isReadOnly(inode)) { |
79 | /* kernel allows writes to devices on read-only | 91 | /* kernel allows writes to devices on read-only |
80 | * partitions and may think inode is dirty | 92 | * partitions and may think inode is dirty |
81 | */ | 93 | */ |
82 | if (!special_file(inode->i_mode) && noisy) { | 94 | if (!special_file(inode->i_mode) && noisy) { |
83 | jfs_err("jfs_commit_inode(0x%p) called on " | 95 | jfs_err("jfs_commit_inode(0x%p) called on " |
84 | "read-only volume", inode); | 96 | "read-only volume", inode); |
85 | jfs_err("Is remount racy?"); | 97 | jfs_err("Is remount racy?"); |
86 | noisy--; | 98 | noisy--; |
87 | } | 99 | } |
88 | return 0; | 100 | return 0; |
89 | } | 101 | } |
90 | 102 | ||
91 | tid = txBegin(inode->i_sb, COMMIT_INODE); | 103 | tid = txBegin(inode->i_sb, COMMIT_INODE); |
92 | mutex_lock(&JFS_IP(inode)->commit_mutex); | 104 | mutex_lock(&JFS_IP(inode)->commit_mutex); |
93 | 105 | ||
94 | /* | 106 | /* |
95 | * Retest inode state after taking commit_mutex | 107 | * Retest inode state after taking commit_mutex |
96 | */ | 108 | */ |
97 | if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) | 109 | if (inode->i_nlink && test_cflag(COMMIT_Dirty, inode)) |
98 | rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); | 110 | rc = txCommit(tid, 1, &inode, wait ? COMMIT_SYNC : 0); |
99 | 111 | ||
100 | txEnd(tid); | 112 | txEnd(tid); |
101 | mutex_unlock(&JFS_IP(inode)->commit_mutex); | 113 | mutex_unlock(&JFS_IP(inode)->commit_mutex); |
102 | return rc; | 114 | return rc; |
103 | } | 115 | } |
104 | 116 | ||
105 | int jfs_write_inode(struct inode *inode, int wait) | 117 | int jfs_write_inode(struct inode *inode, int wait) |
106 | { | 118 | { |
107 | if (test_cflag(COMMIT_Nolink, inode)) | 119 | if (test_cflag(COMMIT_Nolink, inode)) |
108 | return 0; | 120 | return 0; |
109 | /* | 121 | /* |
110 | * If COMMIT_DIRTY is not set, the inode isn't really dirty. | 122 | * If COMMIT_DIRTY is not set, the inode isn't really dirty. |
111 | * It has been committed since the last change, but was still | 123 | * It has been committed since the last change, but was still |
112 | * on the dirty inode list. | 124 | * on the dirty inode list. |
113 | */ | 125 | */ |
114 | if (!test_cflag(COMMIT_Dirty, inode)) { | 126 | if (!test_cflag(COMMIT_Dirty, inode)) { |
115 | /* Make sure committed changes hit the disk */ | 127 | /* Make sure committed changes hit the disk */ |
116 | jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait); | 128 | jfs_flush_journal(JFS_SBI(inode->i_sb)->log, wait); |
117 | return 0; | 129 | return 0; |
118 | } | 130 | } |
119 | 131 | ||
120 | if (jfs_commit_inode(inode, wait)) { | 132 | if (jfs_commit_inode(inode, wait)) { |
121 | jfs_err("jfs_write_inode: jfs_commit_inode failed!"); | 133 | jfs_err("jfs_write_inode: jfs_commit_inode failed!"); |
122 | return -EIO; | 134 | return -EIO; |
123 | } else | 135 | } else |
124 | return 0; | 136 | return 0; |
125 | } | 137 | } |
126 | 138 | ||
127 | void jfs_delete_inode(struct inode *inode) | 139 | void jfs_delete_inode(struct inode *inode) |
128 | { | 140 | { |
129 | jfs_info("In jfs_delete_inode, inode = 0x%p", inode); | 141 | jfs_info("In jfs_delete_inode, inode = 0x%p", inode); |
130 | 142 | ||
131 | if (!is_bad_inode(inode) && | 143 | if (!is_bad_inode(inode) && |
132 | (JFS_IP(inode)->fileset == FILESYSTEM_I)) { | 144 | (JFS_IP(inode)->fileset == FILESYSTEM_I)) { |
133 | truncate_inode_pages(&inode->i_data, 0); | 145 | truncate_inode_pages(&inode->i_data, 0); |
134 | 146 | ||
135 | if (test_cflag(COMMIT_Freewmap, inode)) | 147 | if (test_cflag(COMMIT_Freewmap, inode)) |
136 | jfs_free_zero_link(inode); | 148 | jfs_free_zero_link(inode); |
137 | 149 | ||
138 | diFree(inode); | 150 | diFree(inode); |
139 | 151 | ||
140 | /* | 152 | /* |
141 | * Free the inode from the quota allocation. | 153 | * Free the inode from the quota allocation. |
142 | */ | 154 | */ |
143 | DQUOT_INIT(inode); | 155 | DQUOT_INIT(inode); |
144 | DQUOT_FREE_INODE(inode); | 156 | DQUOT_FREE_INODE(inode); |
145 | DQUOT_DROP(inode); | 157 | DQUOT_DROP(inode); |
146 | } | 158 | } |
147 | 159 | ||
148 | clear_inode(inode); | 160 | clear_inode(inode); |
149 | } | 161 | } |
150 | 162 | ||
151 | void jfs_dirty_inode(struct inode *inode) | 163 | void jfs_dirty_inode(struct inode *inode) |
152 | { | 164 | { |
153 | static int noisy = 5; | 165 | static int noisy = 5; |
154 | 166 | ||
155 | if (isReadOnly(inode)) { | 167 | if (isReadOnly(inode)) { |
156 | if (!special_file(inode->i_mode) && noisy) { | 168 | if (!special_file(inode->i_mode) && noisy) { |
157 | /* kernel allows writes to devices on read-only | 169 | /* kernel allows writes to devices on read-only |
158 | * partitions and may try to mark inode dirty | 170 | * partitions and may try to mark inode dirty |
159 | */ | 171 | */ |
160 | jfs_err("jfs_dirty_inode called on read-only volume"); | 172 | jfs_err("jfs_dirty_inode called on read-only volume"); |
161 | jfs_err("Is remount racy?"); | 173 | jfs_err("Is remount racy?"); |
162 | noisy--; | 174 | noisy--; |
163 | } | 175 | } |
164 | return; | 176 | return; |
165 | } | 177 | } |
166 | 178 | ||
167 | set_cflag(COMMIT_Dirty, inode); | 179 | set_cflag(COMMIT_Dirty, inode); |
168 | } | 180 | } |
169 | 181 | ||
170 | int jfs_get_block(struct inode *ip, sector_t lblock, | 182 | int jfs_get_block(struct inode *ip, sector_t lblock, |
171 | struct buffer_head *bh_result, int create) | 183 | struct buffer_head *bh_result, int create) |
172 | { | 184 | { |
173 | s64 lblock64 = lblock; | 185 | s64 lblock64 = lblock; |
174 | int rc = 0; | 186 | int rc = 0; |
175 | xad_t xad; | 187 | xad_t xad; |
176 | s64 xaddr; | 188 | s64 xaddr; |
177 | int xflag; | 189 | int xflag; |
178 | s32 xlen = bh_result->b_size >> ip->i_blkbits; | 190 | s32 xlen = bh_result->b_size >> ip->i_blkbits; |
179 | 191 | ||
180 | /* | 192 | /* |
181 | * Take appropriate lock on inode | 193 | * Take appropriate lock on inode |
182 | */ | 194 | */ |
183 | if (create) | 195 | if (create) |
184 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); | 196 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); |
185 | else | 197 | else |
186 | IREAD_LOCK(ip, RDWRLOCK_NORMAL); | 198 | IREAD_LOCK(ip, RDWRLOCK_NORMAL); |
187 | 199 | ||
188 | if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && | 200 | if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) && |
189 | (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && | 201 | (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) && |
190 | xaddr) { | 202 | xaddr) { |
191 | if (xflag & XAD_NOTRECORDED) { | 203 | if (xflag & XAD_NOTRECORDED) { |
192 | if (!create) | 204 | if (!create) |
193 | /* | 205 | /* |
194 | * Allocated but not recorded, read treats | 206 | * Allocated but not recorded, read treats |
195 | * this as a hole | 207 | * this as a hole |
196 | */ | 208 | */ |
197 | goto unlock; | 209 | goto unlock; |
198 | #ifdef _JFS_4K | 210 | #ifdef _JFS_4K |
199 | XADoffset(&xad, lblock64); | 211 | XADoffset(&xad, lblock64); |
200 | XADlength(&xad, xlen); | 212 | XADlength(&xad, xlen); |
201 | XADaddress(&xad, xaddr); | 213 | XADaddress(&xad, xaddr); |
202 | #else /* _JFS_4K */ | 214 | #else /* _JFS_4K */ |
203 | /* | 215 | /* |
204 | * As long as block size = 4K, this isn't a problem. | 216 | * As long as block size = 4K, this isn't a problem. |
205 | * We should mark the whole page not ABNR, but how | 217 | * We should mark the whole page not ABNR, but how |
206 | * will we know to mark the other blocks BH_New? | 218 | * will we know to mark the other blocks BH_New? |
207 | */ | 219 | */ |
208 | BUG(); | 220 | BUG(); |
209 | #endif /* _JFS_4K */ | 221 | #endif /* _JFS_4K */ |
210 | rc = extRecord(ip, &xad); | 222 | rc = extRecord(ip, &xad); |
211 | if (rc) | 223 | if (rc) |
212 | goto unlock; | 224 | goto unlock; |
213 | set_buffer_new(bh_result); | 225 | set_buffer_new(bh_result); |
214 | } | 226 | } |
215 | 227 | ||
216 | map_bh(bh_result, ip->i_sb, xaddr); | 228 | map_bh(bh_result, ip->i_sb, xaddr); |
217 | bh_result->b_size = xlen << ip->i_blkbits; | 229 | bh_result->b_size = xlen << ip->i_blkbits; |
218 | goto unlock; | 230 | goto unlock; |
219 | } | 231 | } |
220 | if (!create) | 232 | if (!create) |
221 | goto unlock; | 233 | goto unlock; |
222 | 234 | ||
223 | /* | 235 | /* |
224 | * Allocate a new block | 236 | * Allocate a new block |
225 | */ | 237 | */ |
226 | #ifdef _JFS_4K | 238 | #ifdef _JFS_4K |
227 | if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) | 239 | if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad))) |
228 | goto unlock; | 240 | goto unlock; |
229 | rc = extAlloc(ip, xlen, lblock64, &xad, false); | 241 | rc = extAlloc(ip, xlen, lblock64, &xad, false); |
230 | if (rc) | 242 | if (rc) |
231 | goto unlock; | 243 | goto unlock; |
232 | 244 | ||
233 | set_buffer_new(bh_result); | 245 | set_buffer_new(bh_result); |
234 | map_bh(bh_result, ip->i_sb, addressXAD(&xad)); | 246 | map_bh(bh_result, ip->i_sb, addressXAD(&xad)); |
235 | bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; | 247 | bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits; |
236 | 248 | ||
237 | #else /* _JFS_4K */ | 249 | #else /* _JFS_4K */ |
238 | /* | 250 | /* |
239 | * We need to do whatever it takes to keep all but the last buffers | 251 | * We need to do whatever it takes to keep all but the last buffers |
240 | * in 4K pages - see jfs_write.c | 252 | * in 4K pages - see jfs_write.c |
241 | */ | 253 | */ |
242 | BUG(); | 254 | BUG(); |
243 | #endif /* _JFS_4K */ | 255 | #endif /* _JFS_4K */ |
244 | 256 | ||
245 | unlock: | 257 | unlock: |
246 | /* | 258 | /* |
247 | * Release lock on inode | 259 | * Release lock on inode |
248 | */ | 260 | */ |
249 | if (create) | 261 | if (create) |
250 | IWRITE_UNLOCK(ip); | 262 | IWRITE_UNLOCK(ip); |
251 | else | 263 | else |
252 | IREAD_UNLOCK(ip); | 264 | IREAD_UNLOCK(ip); |
253 | return rc; | 265 | return rc; |
254 | } | 266 | } |
255 | 267 | ||
256 | static int jfs_writepage(struct page *page, struct writeback_control *wbc) | 268 | static int jfs_writepage(struct page *page, struct writeback_control *wbc) |
257 | { | 269 | { |
258 | return block_write_full_page(page, jfs_get_block, wbc); | 270 | return block_write_full_page(page, jfs_get_block, wbc); |
259 | } | 271 | } |
260 | 272 | ||
261 | static int jfs_writepages(struct address_space *mapping, | 273 | static int jfs_writepages(struct address_space *mapping, |
262 | struct writeback_control *wbc) | 274 | struct writeback_control *wbc) |
263 | { | 275 | { |
264 | return mpage_writepages(mapping, wbc, jfs_get_block); | 276 | return mpage_writepages(mapping, wbc, jfs_get_block); |
265 | } | 277 | } |
266 | 278 | ||
267 | static int jfs_readpage(struct file *file, struct page *page) | 279 | static int jfs_readpage(struct file *file, struct page *page) |
268 | { | 280 | { |
269 | return mpage_readpage(page, jfs_get_block); | 281 | return mpage_readpage(page, jfs_get_block); |
270 | } | 282 | } |
271 | 283 | ||
272 | static int jfs_readpages(struct file *file, struct address_space *mapping, | 284 | static int jfs_readpages(struct file *file, struct address_space *mapping, |
273 | struct list_head *pages, unsigned nr_pages) | 285 | struct list_head *pages, unsigned nr_pages) |
274 | { | 286 | { |
275 | return mpage_readpages(mapping, pages, nr_pages, jfs_get_block); | 287 | return mpage_readpages(mapping, pages, nr_pages, jfs_get_block); |
276 | } | 288 | } |
277 | 289 | ||
278 | static int jfs_write_begin(struct file *file, struct address_space *mapping, | 290 | static int jfs_write_begin(struct file *file, struct address_space *mapping, |
279 | loff_t pos, unsigned len, unsigned flags, | 291 | loff_t pos, unsigned len, unsigned flags, |
280 | struct page **pagep, void **fsdata) | 292 | struct page **pagep, void **fsdata) |
281 | { | 293 | { |
282 | return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata, | 294 | return nobh_write_begin(file, mapping, pos, len, flags, pagep, fsdata, |
283 | jfs_get_block); | 295 | jfs_get_block); |
284 | } | 296 | } |
285 | 297 | ||
286 | static sector_t jfs_bmap(struct address_space *mapping, sector_t block) | 298 | static sector_t jfs_bmap(struct address_space *mapping, sector_t block) |
287 | { | 299 | { |
288 | return generic_block_bmap(mapping, block, jfs_get_block); | 300 | return generic_block_bmap(mapping, block, jfs_get_block); |
289 | } | 301 | } |
290 | 302 | ||
291 | static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, | 303 | static ssize_t jfs_direct_IO(int rw, struct kiocb *iocb, |
292 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) | 304 | const struct iovec *iov, loff_t offset, unsigned long nr_segs) |
293 | { | 305 | { |
294 | struct file *file = iocb->ki_filp; | 306 | struct file *file = iocb->ki_filp; |
295 | struct inode *inode = file->f_mapping->host; | 307 | struct inode *inode = file->f_mapping->host; |
296 | 308 | ||
297 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, | 309 | return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, |
298 | offset, nr_segs, jfs_get_block, NULL); | 310 | offset, nr_segs, jfs_get_block, NULL); |
299 | } | 311 | } |
300 | 312 | ||
301 | const struct address_space_operations jfs_aops = { | 313 | const struct address_space_operations jfs_aops = { |
302 | .readpage = jfs_readpage, | 314 | .readpage = jfs_readpage, |
303 | .readpages = jfs_readpages, | 315 | .readpages = jfs_readpages, |
304 | .writepage = jfs_writepage, | 316 | .writepage = jfs_writepage, |
305 | .writepages = jfs_writepages, | 317 | .writepages = jfs_writepages, |
306 | .sync_page = block_sync_page, | 318 | .sync_page = block_sync_page, |
307 | .write_begin = jfs_write_begin, | 319 | .write_begin = jfs_write_begin, |
308 | .write_end = nobh_write_end, | 320 | .write_end = nobh_write_end, |
309 | .bmap = jfs_bmap, | 321 | .bmap = jfs_bmap, |
310 | .direct_IO = jfs_direct_IO, | 322 | .direct_IO = jfs_direct_IO, |
311 | }; | 323 | }; |
312 | 324 | ||
313 | /* | 325 | /* |
314 | * Guts of jfs_truncate. Called with locks already held. Can be called | 326 | * Guts of jfs_truncate. Called with locks already held. Can be called |
315 | * with directory for truncating directory index table. | 327 | * with directory for truncating directory index table. |
316 | */ | 328 | */ |
317 | void jfs_truncate_nolock(struct inode *ip, loff_t length) | 329 | void jfs_truncate_nolock(struct inode *ip, loff_t length) |
318 | { | 330 | { |
319 | loff_t newsize; | 331 | loff_t newsize; |
320 | tid_t tid; | 332 | tid_t tid; |
321 | 333 | ||
322 | ASSERT(length >= 0); | 334 | ASSERT(length >= 0); |
323 | 335 | ||
324 | if (test_cflag(COMMIT_Nolink, ip)) { | 336 | if (test_cflag(COMMIT_Nolink, ip)) { |
325 | xtTruncate(0, ip, length, COMMIT_WMAP); | 337 | xtTruncate(0, ip, length, COMMIT_WMAP); |
326 | return; | 338 | return; |
327 | } | 339 | } |
328 | 340 | ||
329 | do { | 341 | do { |
330 | tid = txBegin(ip->i_sb, 0); | 342 | tid = txBegin(ip->i_sb, 0); |
331 | 343 | ||
332 | /* | 344 | /* |
333 | * The commit_mutex cannot be taken before txBegin. | 345 | * The commit_mutex cannot be taken before txBegin. |
334 | * txBegin may block and there is a chance the inode | 346 | * txBegin may block and there is a chance the inode |
335 | * could be marked dirty and need to be committed | 347 | * could be marked dirty and need to be committed |
336 | * before txBegin unblocks | 348 | * before txBegin unblocks |
337 | */ | 349 | */ |
338 | mutex_lock(&JFS_IP(ip)->commit_mutex); | 350 | mutex_lock(&JFS_IP(ip)->commit_mutex); |
339 | 351 | ||
340 | newsize = xtTruncate(tid, ip, length, | 352 | newsize = xtTruncate(tid, ip, length, |
341 | COMMIT_TRUNCATE | COMMIT_PWMAP); | 353 | COMMIT_TRUNCATE | COMMIT_PWMAP); |
342 | if (newsize < 0) { | 354 | if (newsize < 0) { |
343 | txEnd(tid); | 355 | txEnd(tid); |
344 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 356 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
345 | break; | 357 | break; |
346 | } | 358 | } |
347 | 359 | ||
348 | ip->i_mtime = ip->i_ctime = CURRENT_TIME; | 360 | ip->i_mtime = ip->i_ctime = CURRENT_TIME; |
349 | mark_inode_dirty(ip); | 361 | mark_inode_dirty(ip); |
350 | 362 | ||
351 | txCommit(tid, 1, &ip, 0); | 363 | txCommit(tid, 1, &ip, 0); |
352 | txEnd(tid); | 364 | txEnd(tid); |
353 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 365 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
354 | } while (newsize > length); /* Truncate isn't always atomic */ | 366 | } while (newsize > length); /* Truncate isn't always atomic */ |
355 | } | 367 | } |
356 | 368 | ||
357 | void jfs_truncate(struct inode *ip) | 369 | void jfs_truncate(struct inode *ip) |
358 | { | 370 | { |
359 | jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size); | 371 | jfs_info("jfs_truncate: size = 0x%lx", (ulong) ip->i_size); |
360 | 372 | ||
361 | nobh_truncate_page(ip->i_mapping, ip->i_size, jfs_get_block); | 373 | nobh_truncate_page(ip->i_mapping, ip->i_size, jfs_get_block); |
362 | 374 | ||
363 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); | 375 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); |
364 | jfs_truncate_nolock(ip, ip->i_size); | 376 | jfs_truncate_nolock(ip, ip->i_size); |
365 | IWRITE_UNLOCK(ip); | 377 | IWRITE_UNLOCK(ip); |
366 | } | 378 | } |
367 | 379 |
fs/jfs/jfs_inode.h
1 | /* | 1 | /* |
2 | * Copyright (C) International Business Machines Corp., 2000-2001 | 2 | * Copyright (C) International Business Machines Corp., 2000-2001 |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or | 6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. | 7 | * (at your option) any later version. |
8 | * | 8 | * |
9 | * This program is distributed in the hope that it will be useful, | 9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
12 | * the GNU General Public License for more details. | 12 | * the GNU General Public License for more details. |
13 | * | 13 | * |
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software | 15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | #ifndef _H_JFS_INODE | 18 | #ifndef _H_JFS_INODE |
19 | #define _H_JFS_INODE | 19 | #define _H_JFS_INODE |
20 | 20 | ||
21 | struct fid; | 21 | struct fid; |
22 | 22 | ||
23 | extern struct inode *ialloc(struct inode *, umode_t); | 23 | extern struct inode *ialloc(struct inode *, umode_t); |
24 | extern int jfs_fsync(struct file *, struct dentry *, int); | 24 | extern int jfs_fsync(struct file *, struct dentry *, int); |
25 | extern int jfs_ioctl(struct inode *, struct file *, | 25 | extern int jfs_ioctl(struct inode *, struct file *, |
26 | unsigned int, unsigned long); | 26 | unsigned int, unsigned long); |
27 | extern void jfs_read_inode(struct inode *); | 27 | extern struct inode *jfs_iget(struct super_block *, unsigned long); |
28 | extern int jfs_commit_inode(struct inode *, int); | 28 | extern int jfs_commit_inode(struct inode *, int); |
29 | extern int jfs_write_inode(struct inode*, int); | 29 | extern int jfs_write_inode(struct inode*, int); |
30 | extern void jfs_delete_inode(struct inode *); | 30 | extern void jfs_delete_inode(struct inode *); |
31 | extern void jfs_dirty_inode(struct inode *); | 31 | extern void jfs_dirty_inode(struct inode *); |
32 | extern void jfs_truncate(struct inode *); | 32 | extern void jfs_truncate(struct inode *); |
33 | extern void jfs_truncate_nolock(struct inode *, loff_t); | 33 | extern void jfs_truncate_nolock(struct inode *, loff_t); |
34 | extern void jfs_free_zero_link(struct inode *); | 34 | extern void jfs_free_zero_link(struct inode *); |
35 | extern struct dentry *jfs_get_parent(struct dentry *dentry); | 35 | extern struct dentry *jfs_get_parent(struct dentry *dentry); |
36 | extern void jfs_get_inode_flags(struct jfs_inode_info *); | 36 | extern void jfs_get_inode_flags(struct jfs_inode_info *); |
37 | extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | 37 | extern struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
38 | int fh_len, int fh_type); | 38 | int fh_len, int fh_type); |
39 | extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | 39 | extern struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
40 | int fh_len, int fh_type); | 40 | int fh_len, int fh_type); |
41 | extern void jfs_set_inode_flags(struct inode *); | 41 | extern void jfs_set_inode_flags(struct inode *); |
42 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); | 42 | extern int jfs_get_block(struct inode *, sector_t, struct buffer_head *, int); |
43 | 43 | ||
44 | extern const struct address_space_operations jfs_aops; | 44 | extern const struct address_space_operations jfs_aops; |
45 | extern const struct inode_operations jfs_dir_inode_operations; | 45 | extern const struct inode_operations jfs_dir_inode_operations; |
46 | extern const struct file_operations jfs_dir_operations; | 46 | extern const struct file_operations jfs_dir_operations; |
47 | extern const struct inode_operations jfs_file_inode_operations; | 47 | extern const struct inode_operations jfs_file_inode_operations; |
48 | extern const struct file_operations jfs_file_operations; | 48 | extern const struct file_operations jfs_file_operations; |
49 | extern const struct inode_operations jfs_symlink_inode_operations; | 49 | extern const struct inode_operations jfs_symlink_inode_operations; |
50 | extern struct dentry_operations jfs_ci_dentry_operations; | 50 | extern struct dentry_operations jfs_ci_dentry_operations; |
51 | #endif /* _H_JFS_INODE */ | 51 | #endif /* _H_JFS_INODE */ |
52 | 52 |
fs/jfs/namei.c
1 | /* | 1 | /* |
2 | * Copyright (C) International Business Machines Corp., 2000-2004 | 2 | * Copyright (C) International Business Machines Corp., 2000-2004 |
3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 | 3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
13 | * the GNU General Public License for more details. | 13 | * the GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/quotaops.h> | 22 | #include <linux/quotaops.h> |
23 | #include <linux/exportfs.h> | 23 | #include <linux/exportfs.h> |
24 | #include "jfs_incore.h" | 24 | #include "jfs_incore.h" |
25 | #include "jfs_superblock.h" | 25 | #include "jfs_superblock.h" |
26 | #include "jfs_inode.h" | 26 | #include "jfs_inode.h" |
27 | #include "jfs_dinode.h" | 27 | #include "jfs_dinode.h" |
28 | #include "jfs_dmap.h" | 28 | #include "jfs_dmap.h" |
29 | #include "jfs_unicode.h" | 29 | #include "jfs_unicode.h" |
30 | #include "jfs_metapage.h" | 30 | #include "jfs_metapage.h" |
31 | #include "jfs_xattr.h" | 31 | #include "jfs_xattr.h" |
32 | #include "jfs_acl.h" | 32 | #include "jfs_acl.h" |
33 | #include "jfs_debug.h" | 33 | #include "jfs_debug.h" |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * forward references | 36 | * forward references |
37 | */ | 37 | */ |
38 | struct dentry_operations jfs_ci_dentry_operations; | 38 | struct dentry_operations jfs_ci_dentry_operations; |
39 | 39 | ||
40 | static s64 commitZeroLink(tid_t, struct inode *); | 40 | static s64 commitZeroLink(tid_t, struct inode *); |
41 | 41 | ||
42 | /* | 42 | /* |
43 | * NAME: free_ea_wmap(inode) | 43 | * NAME: free_ea_wmap(inode) |
44 | * | 44 | * |
45 | * FUNCTION: free uncommitted extended attributes from working map | 45 | * FUNCTION: free uncommitted extended attributes from working map |
46 | * | 46 | * |
47 | */ | 47 | */ |
48 | static inline void free_ea_wmap(struct inode *inode) | 48 | static inline void free_ea_wmap(struct inode *inode) |
49 | { | 49 | { |
50 | dxd_t *ea = &JFS_IP(inode)->ea; | 50 | dxd_t *ea = &JFS_IP(inode)->ea; |
51 | 51 | ||
52 | if (ea->flag & DXD_EXTENT) { | 52 | if (ea->flag & DXD_EXTENT) { |
53 | /* free EA pages from cache */ | 53 | /* free EA pages from cache */ |
54 | invalidate_dxd_metapages(inode, *ea); | 54 | invalidate_dxd_metapages(inode, *ea); |
55 | dbFree(inode, addressDXD(ea), lengthDXD(ea)); | 55 | dbFree(inode, addressDXD(ea), lengthDXD(ea)); |
56 | } | 56 | } |
57 | ea->flag = 0; | 57 | ea->flag = 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | /* | 60 | /* |
61 | * NAME: jfs_create(dip, dentry, mode) | 61 | * NAME: jfs_create(dip, dentry, mode) |
62 | * | 62 | * |
63 | * FUNCTION: create a regular file in the parent directory <dip> | 63 | * FUNCTION: create a regular file in the parent directory <dip> |
64 | * with name = <from dentry> and mode = <mode> | 64 | * with name = <from dentry> and mode = <mode> |
65 | * | 65 | * |
66 | * PARAMETER: dip - parent directory vnode | 66 | * PARAMETER: dip - parent directory vnode |
67 | * dentry - dentry of new file | 67 | * dentry - dentry of new file |
68 | * mode - create mode (rwxrwxrwx). | 68 | * mode - create mode (rwxrwxrwx). |
69 | * nd- nd struct | 69 | * nd- nd struct |
70 | * | 70 | * |
71 | * RETURN: Errors from subroutines | 71 | * RETURN: Errors from subroutines |
72 | * | 72 | * |
73 | */ | 73 | */ |
74 | static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, | 74 | static int jfs_create(struct inode *dip, struct dentry *dentry, int mode, |
75 | struct nameidata *nd) | 75 | struct nameidata *nd) |
76 | { | 76 | { |
77 | int rc = 0; | 77 | int rc = 0; |
78 | tid_t tid; /* transaction id */ | 78 | tid_t tid; /* transaction id */ |
79 | struct inode *ip = NULL; /* child directory inode */ | 79 | struct inode *ip = NULL; /* child directory inode */ |
80 | ino_t ino; | 80 | ino_t ino; |
81 | struct component_name dname; /* child directory name */ | 81 | struct component_name dname; /* child directory name */ |
82 | struct btstack btstack; | 82 | struct btstack btstack; |
83 | struct inode *iplist[2]; | 83 | struct inode *iplist[2]; |
84 | struct tblock *tblk; | 84 | struct tblock *tblk; |
85 | 85 | ||
86 | jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name); | 86 | jfs_info("jfs_create: dip:0x%p name:%s", dip, dentry->d_name.name); |
87 | 87 | ||
88 | /* | 88 | /* |
89 | * search parent directory for entry/freespace | 89 | * search parent directory for entry/freespace |
90 | * (dtSearch() returns parent directory page pinned) | 90 | * (dtSearch() returns parent directory page pinned) |
91 | */ | 91 | */ |
92 | if ((rc = get_UCSname(&dname, dentry))) | 92 | if ((rc = get_UCSname(&dname, dentry))) |
93 | goto out1; | 93 | goto out1; |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * Either iAlloc() or txBegin() may block. Deadlock can occur if we | 96 | * Either iAlloc() or txBegin() may block. Deadlock can occur if we |
97 | * block there while holding dtree page, so we allocate the inode & | 97 | * block there while holding dtree page, so we allocate the inode & |
98 | * begin the transaction before we search the directory. | 98 | * begin the transaction before we search the directory. |
99 | */ | 99 | */ |
100 | ip = ialloc(dip, mode); | 100 | ip = ialloc(dip, mode); |
101 | if (IS_ERR(ip)) { | 101 | if (IS_ERR(ip)) { |
102 | rc = PTR_ERR(ip); | 102 | rc = PTR_ERR(ip); |
103 | goto out2; | 103 | goto out2; |
104 | } | 104 | } |
105 | 105 | ||
106 | tid = txBegin(dip->i_sb, 0); | 106 | tid = txBegin(dip->i_sb, 0); |
107 | 107 | ||
108 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 108 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
109 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 109 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
110 | 110 | ||
111 | rc = jfs_init_acl(tid, ip, dip); | 111 | rc = jfs_init_acl(tid, ip, dip); |
112 | if (rc) | 112 | if (rc) |
113 | goto out3; | 113 | goto out3; |
114 | 114 | ||
115 | rc = jfs_init_security(tid, ip, dip); | 115 | rc = jfs_init_security(tid, ip, dip); |
116 | if (rc) { | 116 | if (rc) { |
117 | txAbort(tid, 0); | 117 | txAbort(tid, 0); |
118 | goto out3; | 118 | goto out3; |
119 | } | 119 | } |
120 | 120 | ||
121 | if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { | 121 | if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { |
122 | jfs_err("jfs_create: dtSearch returned %d", rc); | 122 | jfs_err("jfs_create: dtSearch returned %d", rc); |
123 | txAbort(tid, 0); | 123 | txAbort(tid, 0); |
124 | goto out3; | 124 | goto out3; |
125 | } | 125 | } |
126 | 126 | ||
127 | tblk = tid_to_tblock(tid); | 127 | tblk = tid_to_tblock(tid); |
128 | tblk->xflag |= COMMIT_CREATE; | 128 | tblk->xflag |= COMMIT_CREATE; |
129 | tblk->ino = ip->i_ino; | 129 | tblk->ino = ip->i_ino; |
130 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; | 130 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; |
131 | 131 | ||
132 | iplist[0] = dip; | 132 | iplist[0] = dip; |
133 | iplist[1] = ip; | 133 | iplist[1] = ip; |
134 | 134 | ||
135 | /* | 135 | /* |
136 | * initialize the child XAD tree root in-line in inode | 136 | * initialize the child XAD tree root in-line in inode |
137 | */ | 137 | */ |
138 | xtInitRoot(tid, ip); | 138 | xtInitRoot(tid, ip); |
139 | 139 | ||
140 | /* | 140 | /* |
141 | * create entry in parent directory for child directory | 141 | * create entry in parent directory for child directory |
142 | * (dtInsert() releases parent directory page) | 142 | * (dtInsert() releases parent directory page) |
143 | */ | 143 | */ |
144 | ino = ip->i_ino; | 144 | ino = ip->i_ino; |
145 | if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { | 145 | if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { |
146 | if (rc == -EIO) { | 146 | if (rc == -EIO) { |
147 | jfs_err("jfs_create: dtInsert returned -EIO"); | 147 | jfs_err("jfs_create: dtInsert returned -EIO"); |
148 | txAbort(tid, 1); /* Marks Filesystem dirty */ | 148 | txAbort(tid, 1); /* Marks Filesystem dirty */ |
149 | } else | 149 | } else |
150 | txAbort(tid, 0); /* Filesystem full */ | 150 | txAbort(tid, 0); /* Filesystem full */ |
151 | goto out3; | 151 | goto out3; |
152 | } | 152 | } |
153 | 153 | ||
154 | ip->i_op = &jfs_file_inode_operations; | 154 | ip->i_op = &jfs_file_inode_operations; |
155 | ip->i_fop = &jfs_file_operations; | 155 | ip->i_fop = &jfs_file_operations; |
156 | ip->i_mapping->a_ops = &jfs_aops; | 156 | ip->i_mapping->a_ops = &jfs_aops; |
157 | 157 | ||
158 | insert_inode_hash(ip); | 158 | insert_inode_hash(ip); |
159 | mark_inode_dirty(ip); | 159 | mark_inode_dirty(ip); |
160 | 160 | ||
161 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 161 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
162 | 162 | ||
163 | mark_inode_dirty(dip); | 163 | mark_inode_dirty(dip); |
164 | 164 | ||
165 | rc = txCommit(tid, 2, &iplist[0], 0); | 165 | rc = txCommit(tid, 2, &iplist[0], 0); |
166 | 166 | ||
167 | out3: | 167 | out3: |
168 | txEnd(tid); | 168 | txEnd(tid); |
169 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 169 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
170 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 170 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
171 | if (rc) { | 171 | if (rc) { |
172 | free_ea_wmap(ip); | 172 | free_ea_wmap(ip); |
173 | ip->i_nlink = 0; | 173 | ip->i_nlink = 0; |
174 | iput(ip); | 174 | iput(ip); |
175 | } else | 175 | } else |
176 | d_instantiate(dentry, ip); | 176 | d_instantiate(dentry, ip); |
177 | 177 | ||
178 | out2: | 178 | out2: |
179 | free_UCSname(&dname); | 179 | free_UCSname(&dname); |
180 | 180 | ||
181 | out1: | 181 | out1: |
182 | 182 | ||
183 | jfs_info("jfs_create: rc:%d", rc); | 183 | jfs_info("jfs_create: rc:%d", rc); |
184 | return rc; | 184 | return rc; |
185 | } | 185 | } |
186 | 186 | ||
187 | 187 | ||
188 | /* | 188 | /* |
189 | * NAME: jfs_mkdir(dip, dentry, mode) | 189 | * NAME: jfs_mkdir(dip, dentry, mode) |
190 | * | 190 | * |
191 | * FUNCTION: create a child directory in the parent directory <dip> | 191 | * FUNCTION: create a child directory in the parent directory <dip> |
192 | * with name = <from dentry> and mode = <mode> | 192 | * with name = <from dentry> and mode = <mode> |
193 | * | 193 | * |
194 | * PARAMETER: dip - parent directory vnode | 194 | * PARAMETER: dip - parent directory vnode |
195 | * dentry - dentry of child directory | 195 | * dentry - dentry of child directory |
196 | * mode - create mode (rwxrwxrwx). | 196 | * mode - create mode (rwxrwxrwx). |
197 | * | 197 | * |
198 | * RETURN: Errors from subroutines | 198 | * RETURN: Errors from subroutines |
199 | * | 199 | * |
200 | * note: | 200 | * note: |
201 | * EACCESS: user needs search+write permission on the parent directory | 201 | * EACCESS: user needs search+write permission on the parent directory |
202 | */ | 202 | */ |
203 | static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) | 203 | static int jfs_mkdir(struct inode *dip, struct dentry *dentry, int mode) |
204 | { | 204 | { |
205 | int rc = 0; | 205 | int rc = 0; |
206 | tid_t tid; /* transaction id */ | 206 | tid_t tid; /* transaction id */ |
207 | struct inode *ip = NULL; /* child directory inode */ | 207 | struct inode *ip = NULL; /* child directory inode */ |
208 | ino_t ino; | 208 | ino_t ino; |
209 | struct component_name dname; /* child directory name */ | 209 | struct component_name dname; /* child directory name */ |
210 | struct btstack btstack; | 210 | struct btstack btstack; |
211 | struct inode *iplist[2]; | 211 | struct inode *iplist[2]; |
212 | struct tblock *tblk; | 212 | struct tblock *tblk; |
213 | 213 | ||
214 | jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name); | 214 | jfs_info("jfs_mkdir: dip:0x%p name:%s", dip, dentry->d_name.name); |
215 | 215 | ||
216 | /* link count overflow on parent directory ? */ | 216 | /* link count overflow on parent directory ? */ |
217 | if (dip->i_nlink == JFS_LINK_MAX) { | 217 | if (dip->i_nlink == JFS_LINK_MAX) { |
218 | rc = -EMLINK; | 218 | rc = -EMLINK; |
219 | goto out1; | 219 | goto out1; |
220 | } | 220 | } |
221 | 221 | ||
222 | /* | 222 | /* |
223 | * search parent directory for entry/freespace | 223 | * search parent directory for entry/freespace |
224 | * (dtSearch() returns parent directory page pinned) | 224 | * (dtSearch() returns parent directory page pinned) |
225 | */ | 225 | */ |
226 | if ((rc = get_UCSname(&dname, dentry))) | 226 | if ((rc = get_UCSname(&dname, dentry))) |
227 | goto out1; | 227 | goto out1; |
228 | 228 | ||
229 | /* | 229 | /* |
230 | * Either iAlloc() or txBegin() may block. Deadlock can occur if we | 230 | * Either iAlloc() or txBegin() may block. Deadlock can occur if we |
231 | * block there while holding dtree page, so we allocate the inode & | 231 | * block there while holding dtree page, so we allocate the inode & |
232 | * begin the transaction before we search the directory. | 232 | * begin the transaction before we search the directory. |
233 | */ | 233 | */ |
234 | ip = ialloc(dip, S_IFDIR | mode); | 234 | ip = ialloc(dip, S_IFDIR | mode); |
235 | if (IS_ERR(ip)) { | 235 | if (IS_ERR(ip)) { |
236 | rc = PTR_ERR(ip); | 236 | rc = PTR_ERR(ip); |
237 | goto out2; | 237 | goto out2; |
238 | } | 238 | } |
239 | 239 | ||
240 | tid = txBegin(dip->i_sb, 0); | 240 | tid = txBegin(dip->i_sb, 0); |
241 | 241 | ||
242 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 242 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
243 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 243 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
244 | 244 | ||
245 | rc = jfs_init_acl(tid, ip, dip); | 245 | rc = jfs_init_acl(tid, ip, dip); |
246 | if (rc) | 246 | if (rc) |
247 | goto out3; | 247 | goto out3; |
248 | 248 | ||
249 | rc = jfs_init_security(tid, ip, dip); | 249 | rc = jfs_init_security(tid, ip, dip); |
250 | if (rc) { | 250 | if (rc) { |
251 | txAbort(tid, 0); | 251 | txAbort(tid, 0); |
252 | goto out3; | 252 | goto out3; |
253 | } | 253 | } |
254 | 254 | ||
255 | if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { | 255 | if ((rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE))) { |
256 | jfs_err("jfs_mkdir: dtSearch returned %d", rc); | 256 | jfs_err("jfs_mkdir: dtSearch returned %d", rc); |
257 | txAbort(tid, 0); | 257 | txAbort(tid, 0); |
258 | goto out3; | 258 | goto out3; |
259 | } | 259 | } |
260 | 260 | ||
261 | tblk = tid_to_tblock(tid); | 261 | tblk = tid_to_tblock(tid); |
262 | tblk->xflag |= COMMIT_CREATE; | 262 | tblk->xflag |= COMMIT_CREATE; |
263 | tblk->ino = ip->i_ino; | 263 | tblk->ino = ip->i_ino; |
264 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; | 264 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; |
265 | 265 | ||
266 | iplist[0] = dip; | 266 | iplist[0] = dip; |
267 | iplist[1] = ip; | 267 | iplist[1] = ip; |
268 | 268 | ||
269 | /* | 269 | /* |
270 | * initialize the child directory in-line in inode | 270 | * initialize the child directory in-line in inode |
271 | */ | 271 | */ |
272 | dtInitRoot(tid, ip, dip->i_ino); | 272 | dtInitRoot(tid, ip, dip->i_ino); |
273 | 273 | ||
274 | /* | 274 | /* |
275 | * create entry in parent directory for child directory | 275 | * create entry in parent directory for child directory |
276 | * (dtInsert() releases parent directory page) | 276 | * (dtInsert() releases parent directory page) |
277 | */ | 277 | */ |
278 | ino = ip->i_ino; | 278 | ino = ip->i_ino; |
279 | if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { | 279 | if ((rc = dtInsert(tid, dip, &dname, &ino, &btstack))) { |
280 | if (rc == -EIO) { | 280 | if (rc == -EIO) { |
281 | jfs_err("jfs_mkdir: dtInsert returned -EIO"); | 281 | jfs_err("jfs_mkdir: dtInsert returned -EIO"); |
282 | txAbort(tid, 1); /* Marks Filesystem dirty */ | 282 | txAbort(tid, 1); /* Marks Filesystem dirty */ |
283 | } else | 283 | } else |
284 | txAbort(tid, 0); /* Filesystem full */ | 284 | txAbort(tid, 0); /* Filesystem full */ |
285 | goto out3; | 285 | goto out3; |
286 | } | 286 | } |
287 | 287 | ||
288 | ip->i_nlink = 2; /* for '.' */ | 288 | ip->i_nlink = 2; /* for '.' */ |
289 | ip->i_op = &jfs_dir_inode_operations; | 289 | ip->i_op = &jfs_dir_inode_operations; |
290 | ip->i_fop = &jfs_dir_operations; | 290 | ip->i_fop = &jfs_dir_operations; |
291 | 291 | ||
292 | insert_inode_hash(ip); | 292 | insert_inode_hash(ip); |
293 | mark_inode_dirty(ip); | 293 | mark_inode_dirty(ip); |
294 | 294 | ||
295 | /* update parent directory inode */ | 295 | /* update parent directory inode */ |
296 | inc_nlink(dip); /* for '..' from child directory */ | 296 | inc_nlink(dip); /* for '..' from child directory */ |
297 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 297 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
298 | mark_inode_dirty(dip); | 298 | mark_inode_dirty(dip); |
299 | 299 | ||
300 | rc = txCommit(tid, 2, &iplist[0], 0); | 300 | rc = txCommit(tid, 2, &iplist[0], 0); |
301 | 301 | ||
302 | out3: | 302 | out3: |
303 | txEnd(tid); | 303 | txEnd(tid); |
304 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 304 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
305 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 305 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
306 | if (rc) { | 306 | if (rc) { |
307 | free_ea_wmap(ip); | 307 | free_ea_wmap(ip); |
308 | ip->i_nlink = 0; | 308 | ip->i_nlink = 0; |
309 | iput(ip); | 309 | iput(ip); |
310 | } else | 310 | } else |
311 | d_instantiate(dentry, ip); | 311 | d_instantiate(dentry, ip); |
312 | 312 | ||
313 | out2: | 313 | out2: |
314 | free_UCSname(&dname); | 314 | free_UCSname(&dname); |
315 | 315 | ||
316 | 316 | ||
317 | out1: | 317 | out1: |
318 | 318 | ||
319 | jfs_info("jfs_mkdir: rc:%d", rc); | 319 | jfs_info("jfs_mkdir: rc:%d", rc); |
320 | return rc; | 320 | return rc; |
321 | } | 321 | } |
322 | 322 | ||
323 | /* | 323 | /* |
324 | * NAME: jfs_rmdir(dip, dentry) | 324 | * NAME: jfs_rmdir(dip, dentry) |
325 | * | 325 | * |
326 | * FUNCTION: remove a link to child directory | 326 | * FUNCTION: remove a link to child directory |
327 | * | 327 | * |
328 | * PARAMETER: dip - parent inode | 328 | * PARAMETER: dip - parent inode |
329 | * dentry - child directory dentry | 329 | * dentry - child directory dentry |
330 | * | 330 | * |
331 | * RETURN: -EINVAL - if name is . or .. | 331 | * RETURN: -EINVAL - if name is . or .. |
332 | * -EINVAL - if . or .. exist but are invalid. | 332 | * -EINVAL - if . or .. exist but are invalid. |
333 | * errors from subroutines | 333 | * errors from subroutines |
334 | * | 334 | * |
335 | * note: | 335 | * note: |
336 | * if other threads have the directory open when the last link | 336 | * if other threads have the directory open when the last link |
337 | * is removed, the "." and ".." entries, if present, are removed before | 337 | * is removed, the "." and ".." entries, if present, are removed before |
338 | * rmdir() returns and no new entries may be created in the directory, | 338 | * rmdir() returns and no new entries may be created in the directory, |
339 | * but the directory is not removed until the last reference to | 339 | * but the directory is not removed until the last reference to |
340 | * the directory is released (cf.unlink() of regular file). | 340 | * the directory is released (cf.unlink() of regular file). |
341 | */ | 341 | */ |
342 | static int jfs_rmdir(struct inode *dip, struct dentry *dentry) | 342 | static int jfs_rmdir(struct inode *dip, struct dentry *dentry) |
343 | { | 343 | { |
344 | int rc; | 344 | int rc; |
345 | tid_t tid; /* transaction id */ | 345 | tid_t tid; /* transaction id */ |
346 | struct inode *ip = dentry->d_inode; | 346 | struct inode *ip = dentry->d_inode; |
347 | ino_t ino; | 347 | ino_t ino; |
348 | struct component_name dname; | 348 | struct component_name dname; |
349 | struct inode *iplist[2]; | 349 | struct inode *iplist[2]; |
350 | struct tblock *tblk; | 350 | struct tblock *tblk; |
351 | 351 | ||
352 | jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); | 352 | jfs_info("jfs_rmdir: dip:0x%p name:%s", dip, dentry->d_name.name); |
353 | 353 | ||
354 | /* Init inode for quota operations. */ | 354 | /* Init inode for quota operations. */ |
355 | DQUOT_INIT(ip); | 355 | DQUOT_INIT(ip); |
356 | 356 | ||
357 | /* directory must be empty to be removed */ | 357 | /* directory must be empty to be removed */ |
358 | if (!dtEmpty(ip)) { | 358 | if (!dtEmpty(ip)) { |
359 | rc = -ENOTEMPTY; | 359 | rc = -ENOTEMPTY; |
360 | goto out; | 360 | goto out; |
361 | } | 361 | } |
362 | 362 | ||
363 | if ((rc = get_UCSname(&dname, dentry))) { | 363 | if ((rc = get_UCSname(&dname, dentry))) { |
364 | goto out; | 364 | goto out; |
365 | } | 365 | } |
366 | 366 | ||
367 | tid = txBegin(dip->i_sb, 0); | 367 | tid = txBegin(dip->i_sb, 0); |
368 | 368 | ||
369 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 369 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
370 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 370 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
371 | 371 | ||
372 | iplist[0] = dip; | 372 | iplist[0] = dip; |
373 | iplist[1] = ip; | 373 | iplist[1] = ip; |
374 | 374 | ||
375 | tblk = tid_to_tblock(tid); | 375 | tblk = tid_to_tblock(tid); |
376 | tblk->xflag |= COMMIT_DELETE; | 376 | tblk->xflag |= COMMIT_DELETE; |
377 | tblk->u.ip = ip; | 377 | tblk->u.ip = ip; |
378 | 378 | ||
379 | /* | 379 | /* |
380 | * delete the entry of target directory from parent directory | 380 | * delete the entry of target directory from parent directory |
381 | */ | 381 | */ |
382 | ino = ip->i_ino; | 382 | ino = ip->i_ino; |
383 | if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { | 383 | if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { |
384 | jfs_err("jfs_rmdir: dtDelete returned %d", rc); | 384 | jfs_err("jfs_rmdir: dtDelete returned %d", rc); |
385 | if (rc == -EIO) | 385 | if (rc == -EIO) |
386 | txAbort(tid, 1); | 386 | txAbort(tid, 1); |
387 | txEnd(tid); | 387 | txEnd(tid); |
388 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 388 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
389 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 389 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
390 | 390 | ||
391 | goto out2; | 391 | goto out2; |
392 | } | 392 | } |
393 | 393 | ||
394 | /* update parent directory's link count corresponding | 394 | /* update parent directory's link count corresponding |
395 | * to ".." entry of the target directory deleted | 395 | * to ".." entry of the target directory deleted |
396 | */ | 396 | */ |
397 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 397 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
398 | inode_dec_link_count(dip); | 398 | inode_dec_link_count(dip); |
399 | 399 | ||
400 | /* | 400 | /* |
401 | * OS/2 could have created EA and/or ACL | 401 | * OS/2 could have created EA and/or ACL |
402 | */ | 402 | */ |
403 | /* free EA from both persistent and working map */ | 403 | /* free EA from both persistent and working map */ |
404 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { | 404 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { |
405 | /* free EA pages */ | 405 | /* free EA pages */ |
406 | txEA(tid, ip, &JFS_IP(ip)->ea, NULL); | 406 | txEA(tid, ip, &JFS_IP(ip)->ea, NULL); |
407 | } | 407 | } |
408 | JFS_IP(ip)->ea.flag = 0; | 408 | JFS_IP(ip)->ea.flag = 0; |
409 | 409 | ||
410 | /* free ACL from both persistent and working map */ | 410 | /* free ACL from both persistent and working map */ |
411 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { | 411 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { |
412 | /* free ACL pages */ | 412 | /* free ACL pages */ |
413 | txEA(tid, ip, &JFS_IP(ip)->acl, NULL); | 413 | txEA(tid, ip, &JFS_IP(ip)->acl, NULL); |
414 | } | 414 | } |
415 | JFS_IP(ip)->acl.flag = 0; | 415 | JFS_IP(ip)->acl.flag = 0; |
416 | 416 | ||
417 | /* mark the target directory as deleted */ | 417 | /* mark the target directory as deleted */ |
418 | clear_nlink(ip); | 418 | clear_nlink(ip); |
419 | mark_inode_dirty(ip); | 419 | mark_inode_dirty(ip); |
420 | 420 | ||
421 | rc = txCommit(tid, 2, &iplist[0], 0); | 421 | rc = txCommit(tid, 2, &iplist[0], 0); |
422 | 422 | ||
423 | txEnd(tid); | 423 | txEnd(tid); |
424 | 424 | ||
425 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 425 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
426 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 426 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
427 | 427 | ||
428 | /* | 428 | /* |
429 | * Truncating the directory index table is not guaranteed. It | 429 | * Truncating the directory index table is not guaranteed. It |
430 | * may need to be done iteratively | 430 | * may need to be done iteratively |
431 | */ | 431 | */ |
432 | if (test_cflag(COMMIT_Stale, dip)) { | 432 | if (test_cflag(COMMIT_Stale, dip)) { |
433 | if (dip->i_size > 1) | 433 | if (dip->i_size > 1) |
434 | jfs_truncate_nolock(dip, 0); | 434 | jfs_truncate_nolock(dip, 0); |
435 | 435 | ||
436 | clear_cflag(COMMIT_Stale, dip); | 436 | clear_cflag(COMMIT_Stale, dip); |
437 | } | 437 | } |
438 | 438 | ||
439 | out2: | 439 | out2: |
440 | free_UCSname(&dname); | 440 | free_UCSname(&dname); |
441 | 441 | ||
442 | out: | 442 | out: |
443 | jfs_info("jfs_rmdir: rc:%d", rc); | 443 | jfs_info("jfs_rmdir: rc:%d", rc); |
444 | return rc; | 444 | return rc; |
445 | } | 445 | } |
446 | 446 | ||
447 | /* | 447 | /* |
448 | * NAME: jfs_unlink(dip, dentry) | 448 | * NAME: jfs_unlink(dip, dentry) |
449 | * | 449 | * |
450 | * FUNCTION: remove a link to object <vp> named by <name> | 450 | * FUNCTION: remove a link to object <vp> named by <name> |
451 | * from parent directory <dvp> | 451 | * from parent directory <dvp> |
452 | * | 452 | * |
453 | * PARAMETER: dip - inode of parent directory | 453 | * PARAMETER: dip - inode of parent directory |
454 | * dentry - dentry of object to be removed | 454 | * dentry - dentry of object to be removed |
455 | * | 455 | * |
456 | * RETURN: errors from subroutines | 456 | * RETURN: errors from subroutines |
457 | * | 457 | * |
458 | * note: | 458 | * note: |
459 | * temporary file: if one or more processes have the file open | 459 | * temporary file: if one or more processes have the file open |
460 | * when the last link is removed, the link will be removed before | 460 | * when the last link is removed, the link will be removed before |
461 | * unlink() returns, but the removal of the file contents will be | 461 | * unlink() returns, but the removal of the file contents will be |
462 | * postponed until all references to the files are closed. | 462 | * postponed until all references to the files are closed. |
463 | * | 463 | * |
464 | * JFS does NOT support unlink() on directories. | 464 | * JFS does NOT support unlink() on directories. |
465 | * | 465 | * |
466 | */ | 466 | */ |
467 | static int jfs_unlink(struct inode *dip, struct dentry *dentry) | 467 | static int jfs_unlink(struct inode *dip, struct dentry *dentry) |
468 | { | 468 | { |
469 | int rc; | 469 | int rc; |
470 | tid_t tid; /* transaction id */ | 470 | tid_t tid; /* transaction id */ |
471 | struct inode *ip = dentry->d_inode; | 471 | struct inode *ip = dentry->d_inode; |
472 | ino_t ino; | 472 | ino_t ino; |
473 | struct component_name dname; /* object name */ | 473 | struct component_name dname; /* object name */ |
474 | struct inode *iplist[2]; | 474 | struct inode *iplist[2]; |
475 | struct tblock *tblk; | 475 | struct tblock *tblk; |
476 | s64 new_size = 0; | 476 | s64 new_size = 0; |
477 | int commit_flag; | 477 | int commit_flag; |
478 | 478 | ||
479 | jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name); | 479 | jfs_info("jfs_unlink: dip:0x%p name:%s", dip, dentry->d_name.name); |
480 | 480 | ||
481 | /* Init inode for quota operations. */ | 481 | /* Init inode for quota operations. */ |
482 | DQUOT_INIT(ip); | 482 | DQUOT_INIT(ip); |
483 | 483 | ||
484 | if ((rc = get_UCSname(&dname, dentry))) | 484 | if ((rc = get_UCSname(&dname, dentry))) |
485 | goto out; | 485 | goto out; |
486 | 486 | ||
487 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); | 487 | IWRITE_LOCK(ip, RDWRLOCK_NORMAL); |
488 | 488 | ||
489 | tid = txBegin(dip->i_sb, 0); | 489 | tid = txBegin(dip->i_sb, 0); |
490 | 490 | ||
491 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 491 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
492 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 492 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
493 | 493 | ||
494 | iplist[0] = dip; | 494 | iplist[0] = dip; |
495 | iplist[1] = ip; | 495 | iplist[1] = ip; |
496 | 496 | ||
497 | /* | 497 | /* |
498 | * delete the entry of target file from parent directory | 498 | * delete the entry of target file from parent directory |
499 | */ | 499 | */ |
500 | ino = ip->i_ino; | 500 | ino = ip->i_ino; |
501 | if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { | 501 | if ((rc = dtDelete(tid, dip, &dname, &ino, JFS_REMOVE))) { |
502 | jfs_err("jfs_unlink: dtDelete returned %d", rc); | 502 | jfs_err("jfs_unlink: dtDelete returned %d", rc); |
503 | if (rc == -EIO) | 503 | if (rc == -EIO) |
504 | txAbort(tid, 1); /* Marks FS Dirty */ | 504 | txAbort(tid, 1); /* Marks FS Dirty */ |
505 | txEnd(tid); | 505 | txEnd(tid); |
506 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 506 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
507 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 507 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
508 | IWRITE_UNLOCK(ip); | 508 | IWRITE_UNLOCK(ip); |
509 | goto out1; | 509 | goto out1; |
510 | } | 510 | } |
511 | 511 | ||
512 | ASSERT(ip->i_nlink); | 512 | ASSERT(ip->i_nlink); |
513 | 513 | ||
514 | ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 514 | ip->i_ctime = dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
515 | mark_inode_dirty(dip); | 515 | mark_inode_dirty(dip); |
516 | 516 | ||
517 | /* update target's inode */ | 517 | /* update target's inode */ |
518 | inode_dec_link_count(ip); | 518 | inode_dec_link_count(ip); |
519 | 519 | ||
520 | /* | 520 | /* |
521 | * commit zero link count object | 521 | * commit zero link count object |
522 | */ | 522 | */ |
523 | if (ip->i_nlink == 0) { | 523 | if (ip->i_nlink == 0) { |
524 | assert(!test_cflag(COMMIT_Nolink, ip)); | 524 | assert(!test_cflag(COMMIT_Nolink, ip)); |
525 | /* free block resources */ | 525 | /* free block resources */ |
526 | if ((new_size = commitZeroLink(tid, ip)) < 0) { | 526 | if ((new_size = commitZeroLink(tid, ip)) < 0) { |
527 | txAbort(tid, 1); /* Marks FS Dirty */ | 527 | txAbort(tid, 1); /* Marks FS Dirty */ |
528 | txEnd(tid); | 528 | txEnd(tid); |
529 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 529 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
530 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 530 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
531 | IWRITE_UNLOCK(ip); | 531 | IWRITE_UNLOCK(ip); |
532 | rc = new_size; | 532 | rc = new_size; |
533 | goto out1; | 533 | goto out1; |
534 | } | 534 | } |
535 | tblk = tid_to_tblock(tid); | 535 | tblk = tid_to_tblock(tid); |
536 | tblk->xflag |= COMMIT_DELETE; | 536 | tblk->xflag |= COMMIT_DELETE; |
537 | tblk->u.ip = ip; | 537 | tblk->u.ip = ip; |
538 | } | 538 | } |
539 | 539 | ||
540 | /* | 540 | /* |
541 | * Incomplete truncate of file data can | 541 | * Incomplete truncate of file data can |
542 | * result in timing problems unless we synchronously commit the | 542 | * result in timing problems unless we synchronously commit the |
543 | * transaction. | 543 | * transaction. |
544 | */ | 544 | */ |
545 | if (new_size) | 545 | if (new_size) |
546 | commit_flag = COMMIT_SYNC; | 546 | commit_flag = COMMIT_SYNC; |
547 | else | 547 | else |
548 | commit_flag = 0; | 548 | commit_flag = 0; |
549 | 549 | ||
550 | /* | 550 | /* |
551 | * If xtTruncate was incomplete, commit synchronously to avoid | 551 | * If xtTruncate was incomplete, commit synchronously to avoid |
552 | * timing complications | 552 | * timing complications |
553 | */ | 553 | */ |
554 | rc = txCommit(tid, 2, &iplist[0], commit_flag); | 554 | rc = txCommit(tid, 2, &iplist[0], commit_flag); |
555 | 555 | ||
556 | txEnd(tid); | 556 | txEnd(tid); |
557 | 557 | ||
558 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 558 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
559 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 559 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
560 | 560 | ||
561 | while (new_size && (rc == 0)) { | 561 | while (new_size && (rc == 0)) { |
562 | tid = txBegin(dip->i_sb, 0); | 562 | tid = txBegin(dip->i_sb, 0); |
563 | mutex_lock(&JFS_IP(ip)->commit_mutex); | 563 | mutex_lock(&JFS_IP(ip)->commit_mutex); |
564 | new_size = xtTruncate_pmap(tid, ip, new_size); | 564 | new_size = xtTruncate_pmap(tid, ip, new_size); |
565 | if (new_size < 0) { | 565 | if (new_size < 0) { |
566 | txAbort(tid, 1); /* Marks FS Dirty */ | 566 | txAbort(tid, 1); /* Marks FS Dirty */ |
567 | rc = new_size; | 567 | rc = new_size; |
568 | } else | 568 | } else |
569 | rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC); | 569 | rc = txCommit(tid, 2, &iplist[0], COMMIT_SYNC); |
570 | txEnd(tid); | 570 | txEnd(tid); |
571 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 571 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
572 | } | 572 | } |
573 | 573 | ||
574 | if (ip->i_nlink == 0) | 574 | if (ip->i_nlink == 0) |
575 | set_cflag(COMMIT_Nolink, ip); | 575 | set_cflag(COMMIT_Nolink, ip); |
576 | 576 | ||
577 | IWRITE_UNLOCK(ip); | 577 | IWRITE_UNLOCK(ip); |
578 | 578 | ||
579 | /* | 579 | /* |
580 | * Truncating the directory index table is not guaranteed. It | 580 | * Truncating the directory index table is not guaranteed. It |
581 | * may need to be done iteratively | 581 | * may need to be done iteratively |
582 | */ | 582 | */ |
583 | if (test_cflag(COMMIT_Stale, dip)) { | 583 | if (test_cflag(COMMIT_Stale, dip)) { |
584 | if (dip->i_size > 1) | 584 | if (dip->i_size > 1) |
585 | jfs_truncate_nolock(dip, 0); | 585 | jfs_truncate_nolock(dip, 0); |
586 | 586 | ||
587 | clear_cflag(COMMIT_Stale, dip); | 587 | clear_cflag(COMMIT_Stale, dip); |
588 | } | 588 | } |
589 | 589 | ||
590 | out1: | 590 | out1: |
591 | free_UCSname(&dname); | 591 | free_UCSname(&dname); |
592 | out: | 592 | out: |
593 | jfs_info("jfs_unlink: rc:%d", rc); | 593 | jfs_info("jfs_unlink: rc:%d", rc); |
594 | return rc; | 594 | return rc; |
595 | } | 595 | } |
596 | 596 | ||
597 | /* | 597 | /* |
598 | * NAME: commitZeroLink() | 598 | * NAME: commitZeroLink() |
599 | * | 599 | * |
600 | * FUNCTION: for non-directory, called by jfs_remove(), | 600 | * FUNCTION: for non-directory, called by jfs_remove(), |
601 | * truncate a regular file, directory or symbolic | 601 | * truncate a regular file, directory or symbolic |
602 | * link to zero length. return 0 if type is not | 602 | * link to zero length. return 0 if type is not |
603 | * one of these. | 603 | * one of these. |
604 | * | 604 | * |
605 | * if the file is currently associated with a VM segment | 605 | * if the file is currently associated with a VM segment |
606 | * only permanent disk and inode map resources are freed, | 606 | * only permanent disk and inode map resources are freed, |
607 | * and neither the inode nor indirect blocks are modified | 607 | * and neither the inode nor indirect blocks are modified |
608 | * so that the resources can be later freed in the work | 608 | * so that the resources can be later freed in the work |
609 | * map by ctrunc1. | 609 | * map by ctrunc1. |
610 | * if there is no VM segment on entry, the resources are | 610 | * if there is no VM segment on entry, the resources are |
611 | * freed in both work and permanent map. | 611 | * freed in both work and permanent map. |
612 | * (? for temporary file - memory object is cached even | 612 | * (? for temporary file - memory object is cached even |
613 | * after no reference: | 613 | * after no reference: |
614 | * reference count > 0 - ) | 614 | * reference count > 0 - ) |
615 | * | 615 | * |
616 | * PARAMETERS: cd - pointer to commit data structure. | 616 | * PARAMETERS: cd - pointer to commit data structure. |
617 | * current inode is the one to truncate. | 617 | * current inode is the one to truncate. |
618 | * | 618 | * |
619 | * RETURN: Errors from subroutines | 619 | * RETURN: Errors from subroutines |
620 | */ | 620 | */ |
621 | static s64 commitZeroLink(tid_t tid, struct inode *ip) | 621 | static s64 commitZeroLink(tid_t tid, struct inode *ip) |
622 | { | 622 | { |
623 | int filetype; | 623 | int filetype; |
624 | struct tblock *tblk; | 624 | struct tblock *tblk; |
625 | 625 | ||
626 | jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip); | 626 | jfs_info("commitZeroLink: tid = %d, ip = 0x%p", tid, ip); |
627 | 627 | ||
628 | filetype = ip->i_mode & S_IFMT; | 628 | filetype = ip->i_mode & S_IFMT; |
629 | switch (filetype) { | 629 | switch (filetype) { |
630 | case S_IFREG: | 630 | case S_IFREG: |
631 | break; | 631 | break; |
632 | case S_IFLNK: | 632 | case S_IFLNK: |
633 | /* fast symbolic link */ | 633 | /* fast symbolic link */ |
634 | if (ip->i_size < IDATASIZE) { | 634 | if (ip->i_size < IDATASIZE) { |
635 | ip->i_size = 0; | 635 | ip->i_size = 0; |
636 | return 0; | 636 | return 0; |
637 | } | 637 | } |
638 | break; | 638 | break; |
639 | default: | 639 | default: |
640 | assert(filetype != S_IFDIR); | 640 | assert(filetype != S_IFDIR); |
641 | return 0; | 641 | return 0; |
642 | } | 642 | } |
643 | 643 | ||
644 | set_cflag(COMMIT_Freewmap, ip); | 644 | set_cflag(COMMIT_Freewmap, ip); |
645 | 645 | ||
646 | /* mark transaction of block map update type */ | 646 | /* mark transaction of block map update type */ |
647 | tblk = tid_to_tblock(tid); | 647 | tblk = tid_to_tblock(tid); |
648 | tblk->xflag |= COMMIT_PMAP; | 648 | tblk->xflag |= COMMIT_PMAP; |
649 | 649 | ||
650 | /* | 650 | /* |
651 | * free EA | 651 | * free EA |
652 | */ | 652 | */ |
653 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) | 653 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) |
654 | /* acquire maplock on EA to be freed from block map */ | 654 | /* acquire maplock on EA to be freed from block map */ |
655 | txEA(tid, ip, &JFS_IP(ip)->ea, NULL); | 655 | txEA(tid, ip, &JFS_IP(ip)->ea, NULL); |
656 | 656 | ||
657 | /* | 657 | /* |
658 | * free ACL | 658 | * free ACL |
659 | */ | 659 | */ |
660 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) | 660 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) |
661 | /* acquire maplock on EA to be freed from block map */ | 661 | /* acquire maplock on EA to be freed from block map */ |
662 | txEA(tid, ip, &JFS_IP(ip)->acl, NULL); | 662 | txEA(tid, ip, &JFS_IP(ip)->acl, NULL); |
663 | 663 | ||
664 | /* | 664 | /* |
665 | * free xtree/data (truncate to zero length): | 665 | * free xtree/data (truncate to zero length): |
666 | * free xtree/data pages from cache if COMMIT_PWMAP, | 666 | * free xtree/data pages from cache if COMMIT_PWMAP, |
667 | * free xtree/data blocks from persistent block map, and | 667 | * free xtree/data blocks from persistent block map, and |
668 | * free xtree/data blocks from working block map if COMMIT_PWMAP; | 668 | * free xtree/data blocks from working block map if COMMIT_PWMAP; |
669 | */ | 669 | */ |
670 | if (ip->i_size) | 670 | if (ip->i_size) |
671 | return xtTruncate_pmap(tid, ip, 0); | 671 | return xtTruncate_pmap(tid, ip, 0); |
672 | 672 | ||
673 | return 0; | 673 | return 0; |
674 | } | 674 | } |
675 | 675 | ||
676 | 676 | ||
677 | /* | 677 | /* |
678 | * NAME: jfs_free_zero_link() | 678 | * NAME: jfs_free_zero_link() |
679 | * | 679 | * |
680 | * FUNCTION: for non-directory, called by iClose(), | 680 | * FUNCTION: for non-directory, called by iClose(), |
681 | * free resources of a file from cache and WORKING map | 681 | * free resources of a file from cache and WORKING map |
682 | * for a file previously committed with zero link count | 682 | * for a file previously committed with zero link count |
683 | * while associated with a pager object, | 683 | * while associated with a pager object, |
684 | * | 684 | * |
685 | * PARAMETER: ip - pointer to inode of file. | 685 | * PARAMETER: ip - pointer to inode of file. |
686 | */ | 686 | */ |
687 | void jfs_free_zero_link(struct inode *ip) | 687 | void jfs_free_zero_link(struct inode *ip) |
688 | { | 688 | { |
689 | int type; | 689 | int type; |
690 | 690 | ||
691 | jfs_info("jfs_free_zero_link: ip = 0x%p", ip); | 691 | jfs_info("jfs_free_zero_link: ip = 0x%p", ip); |
692 | 692 | ||
693 | /* return if not reg or symbolic link or if size is | 693 | /* return if not reg or symbolic link or if size is |
694 | * already ok. | 694 | * already ok. |
695 | */ | 695 | */ |
696 | type = ip->i_mode & S_IFMT; | 696 | type = ip->i_mode & S_IFMT; |
697 | 697 | ||
698 | switch (type) { | 698 | switch (type) { |
699 | case S_IFREG: | 699 | case S_IFREG: |
700 | break; | 700 | break; |
701 | case S_IFLNK: | 701 | case S_IFLNK: |
702 | /* if its contained in inode nothing to do */ | 702 | /* if its contained in inode nothing to do */ |
703 | if (ip->i_size < IDATASIZE) | 703 | if (ip->i_size < IDATASIZE) |
704 | return; | 704 | return; |
705 | break; | 705 | break; |
706 | default: | 706 | default: |
707 | return; | 707 | return; |
708 | } | 708 | } |
709 | 709 | ||
710 | /* | 710 | /* |
711 | * free EA | 711 | * free EA |
712 | */ | 712 | */ |
713 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { | 713 | if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { |
714 | s64 xaddr = addressDXD(&JFS_IP(ip)->ea); | 714 | s64 xaddr = addressDXD(&JFS_IP(ip)->ea); |
715 | int xlen = lengthDXD(&JFS_IP(ip)->ea); | 715 | int xlen = lengthDXD(&JFS_IP(ip)->ea); |
716 | struct maplock maplock; /* maplock for COMMIT_WMAP */ | 716 | struct maplock maplock; /* maplock for COMMIT_WMAP */ |
717 | struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ | 717 | struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ |
718 | 718 | ||
719 | /* free EA pages from cache */ | 719 | /* free EA pages from cache */ |
720 | invalidate_dxd_metapages(ip, JFS_IP(ip)->ea); | 720 | invalidate_dxd_metapages(ip, JFS_IP(ip)->ea); |
721 | 721 | ||
722 | /* free EA extent from working block map */ | 722 | /* free EA extent from working block map */ |
723 | maplock.index = 1; | 723 | maplock.index = 1; |
724 | pxdlock = (struct pxd_lock *) & maplock; | 724 | pxdlock = (struct pxd_lock *) & maplock; |
725 | pxdlock->flag = mlckFREEPXD; | 725 | pxdlock->flag = mlckFREEPXD; |
726 | PXDaddress(&pxdlock->pxd, xaddr); | 726 | PXDaddress(&pxdlock->pxd, xaddr); |
727 | PXDlength(&pxdlock->pxd, xlen); | 727 | PXDlength(&pxdlock->pxd, xlen); |
728 | txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); | 728 | txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); |
729 | } | 729 | } |
730 | 730 | ||
731 | /* | 731 | /* |
732 | * free ACL | 732 | * free ACL |
733 | */ | 733 | */ |
734 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { | 734 | if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { |
735 | s64 xaddr = addressDXD(&JFS_IP(ip)->acl); | 735 | s64 xaddr = addressDXD(&JFS_IP(ip)->acl); |
736 | int xlen = lengthDXD(&JFS_IP(ip)->acl); | 736 | int xlen = lengthDXD(&JFS_IP(ip)->acl); |
737 | struct maplock maplock; /* maplock for COMMIT_WMAP */ | 737 | struct maplock maplock; /* maplock for COMMIT_WMAP */ |
738 | struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ | 738 | struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ |
739 | 739 | ||
740 | invalidate_dxd_metapages(ip, JFS_IP(ip)->acl); | 740 | invalidate_dxd_metapages(ip, JFS_IP(ip)->acl); |
741 | 741 | ||
742 | /* free ACL extent from working block map */ | 742 | /* free ACL extent from working block map */ |
743 | maplock.index = 1; | 743 | maplock.index = 1; |
744 | pxdlock = (struct pxd_lock *) & maplock; | 744 | pxdlock = (struct pxd_lock *) & maplock; |
745 | pxdlock->flag = mlckFREEPXD; | 745 | pxdlock->flag = mlckFREEPXD; |
746 | PXDaddress(&pxdlock->pxd, xaddr); | 746 | PXDaddress(&pxdlock->pxd, xaddr); |
747 | PXDlength(&pxdlock->pxd, xlen); | 747 | PXDlength(&pxdlock->pxd, xlen); |
748 | txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); | 748 | txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); |
749 | } | 749 | } |
750 | 750 | ||
751 | /* | 751 | /* |
752 | * free xtree/data (truncate to zero length): | 752 | * free xtree/data (truncate to zero length): |
753 | * free xtree/data pages from cache, and | 753 | * free xtree/data pages from cache, and |
754 | * free xtree/data blocks from working block map; | 754 | * free xtree/data blocks from working block map; |
755 | */ | 755 | */ |
756 | if (ip->i_size) | 756 | if (ip->i_size) |
757 | xtTruncate(0, ip, 0, COMMIT_WMAP); | 757 | xtTruncate(0, ip, 0, COMMIT_WMAP); |
758 | } | 758 | } |
759 | 759 | ||
760 | /* | 760 | /* |
761 | * NAME: jfs_link(vp, dvp, name, crp) | 761 | * NAME: jfs_link(vp, dvp, name, crp) |
762 | * | 762 | * |
763 | * FUNCTION: create a link to <vp> by the name = <name> | 763 | * FUNCTION: create a link to <vp> by the name = <name> |
764 | * in the parent directory <dvp> | 764 | * in the parent directory <dvp> |
765 | * | 765 | * |
766 | * PARAMETER: vp - target object | 766 | * PARAMETER: vp - target object |
767 | * dvp - parent directory of new link | 767 | * dvp - parent directory of new link |
768 | * name - name of new link to target object | 768 | * name - name of new link to target object |
769 | * crp - credential | 769 | * crp - credential |
770 | * | 770 | * |
771 | * RETURN: Errors from subroutines | 771 | * RETURN: Errors from subroutines |
772 | * | 772 | * |
773 | * note: | 773 | * note: |
774 | * JFS does NOT support link() on directories (to prevent circular | 774 | * JFS does NOT support link() on directories (to prevent circular |
775 | * path in the directory hierarchy); | 775 | * path in the directory hierarchy); |
776 | * EPERM: the target object is a directory, and either the caller | 776 | * EPERM: the target object is a directory, and either the caller |
777 | * does not have appropriate privileges or the implementation prohibits | 777 | * does not have appropriate privileges or the implementation prohibits |
778 | * using link() on directories [XPG4.2]. | 778 | * using link() on directories [XPG4.2]. |
779 | * | 779 | * |
780 | * JFS does NOT support links between file systems: | 780 | * JFS does NOT support links between file systems: |
781 | * EXDEV: target object and new link are on different file systems and | 781 | * EXDEV: target object and new link are on different file systems and |
782 | * implementation does not support links between file systems [XPG4.2]. | 782 | * implementation does not support links between file systems [XPG4.2]. |
783 | */ | 783 | */ |
784 | static int jfs_link(struct dentry *old_dentry, | 784 | static int jfs_link(struct dentry *old_dentry, |
785 | struct inode *dir, struct dentry *dentry) | 785 | struct inode *dir, struct dentry *dentry) |
786 | { | 786 | { |
787 | int rc; | 787 | int rc; |
788 | tid_t tid; | 788 | tid_t tid; |
789 | struct inode *ip = old_dentry->d_inode; | 789 | struct inode *ip = old_dentry->d_inode; |
790 | ino_t ino; | 790 | ino_t ino; |
791 | struct component_name dname; | 791 | struct component_name dname; |
792 | struct btstack btstack; | 792 | struct btstack btstack; |
793 | struct inode *iplist[2]; | 793 | struct inode *iplist[2]; |
794 | 794 | ||
795 | jfs_info("jfs_link: %s %s", old_dentry->d_name.name, | 795 | jfs_info("jfs_link: %s %s", old_dentry->d_name.name, |
796 | dentry->d_name.name); | 796 | dentry->d_name.name); |
797 | 797 | ||
798 | if (ip->i_nlink == JFS_LINK_MAX) | 798 | if (ip->i_nlink == JFS_LINK_MAX) |
799 | return -EMLINK; | 799 | return -EMLINK; |
800 | 800 | ||
801 | if (ip->i_nlink == 0) | 801 | if (ip->i_nlink == 0) |
802 | return -ENOENT; | 802 | return -ENOENT; |
803 | 803 | ||
804 | tid = txBegin(ip->i_sb, 0); | 804 | tid = txBegin(ip->i_sb, 0); |
805 | 805 | ||
806 | mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); | 806 | mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); |
807 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 807 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
808 | 808 | ||
809 | /* | 809 | /* |
810 | * scan parent directory for entry/freespace | 810 | * scan parent directory for entry/freespace |
811 | */ | 811 | */ |
812 | if ((rc = get_UCSname(&dname, dentry))) | 812 | if ((rc = get_UCSname(&dname, dentry))) |
813 | goto out; | 813 | goto out; |
814 | 814 | ||
815 | if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) | 815 | if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) |
816 | goto free_dname; | 816 | goto free_dname; |
817 | 817 | ||
818 | /* | 818 | /* |
819 | * create entry for new link in parent directory | 819 | * create entry for new link in parent directory |
820 | */ | 820 | */ |
821 | ino = ip->i_ino; | 821 | ino = ip->i_ino; |
822 | if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) | 822 | if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) |
823 | goto free_dname; | 823 | goto free_dname; |
824 | 824 | ||
825 | /* update object inode */ | 825 | /* update object inode */ |
826 | inc_nlink(ip); /* for new link */ | 826 | inc_nlink(ip); /* for new link */ |
827 | ip->i_ctime = CURRENT_TIME; | 827 | ip->i_ctime = CURRENT_TIME; |
828 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 828 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
829 | mark_inode_dirty(dir); | 829 | mark_inode_dirty(dir); |
830 | atomic_inc(&ip->i_count); | 830 | atomic_inc(&ip->i_count); |
831 | 831 | ||
832 | iplist[0] = ip; | 832 | iplist[0] = ip; |
833 | iplist[1] = dir; | 833 | iplist[1] = dir; |
834 | rc = txCommit(tid, 2, &iplist[0], 0); | 834 | rc = txCommit(tid, 2, &iplist[0], 0); |
835 | 835 | ||
836 | if (rc) { | 836 | if (rc) { |
837 | ip->i_nlink--; /* never instantiated */ | 837 | ip->i_nlink--; /* never instantiated */ |
838 | iput(ip); | 838 | iput(ip); |
839 | } else | 839 | } else |
840 | d_instantiate(dentry, ip); | 840 | d_instantiate(dentry, ip); |
841 | 841 | ||
842 | free_dname: | 842 | free_dname: |
843 | free_UCSname(&dname); | 843 | free_UCSname(&dname); |
844 | 844 | ||
845 | out: | 845 | out: |
846 | txEnd(tid); | 846 | txEnd(tid); |
847 | 847 | ||
848 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 848 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
849 | mutex_unlock(&JFS_IP(dir)->commit_mutex); | 849 | mutex_unlock(&JFS_IP(dir)->commit_mutex); |
850 | 850 | ||
851 | jfs_info("jfs_link: rc:%d", rc); | 851 | jfs_info("jfs_link: rc:%d", rc); |
852 | return rc; | 852 | return rc; |
853 | } | 853 | } |
854 | 854 | ||
855 | /* | 855 | /* |
856 | * NAME: jfs_symlink(dip, dentry, name) | 856 | * NAME: jfs_symlink(dip, dentry, name) |
857 | * | 857 | * |
858 | * FUNCTION: creates a symbolic link to <symlink> by name <name> | 858 | * FUNCTION: creates a symbolic link to <symlink> by name <name> |
859 | * in directory <dip> | 859 | * in directory <dip> |
860 | * | 860 | * |
861 | * PARAMETER: dip - parent directory vnode | 861 | * PARAMETER: dip - parent directory vnode |
862 | * dentry - dentry of symbolic link | 862 | * dentry - dentry of symbolic link |
863 | * name - the path name of the existing object | 863 | * name - the path name of the existing object |
864 | * that will be the source of the link | 864 | * that will be the source of the link |
865 | * | 865 | * |
866 | * RETURN: errors from subroutines | 866 | * RETURN: errors from subroutines |
867 | * | 867 | * |
868 | * note: | 868 | * note: |
869 | * ENAMETOOLONG: pathname resolution of a symbolic link produced | 869 | * ENAMETOOLONG: pathname resolution of a symbolic link produced |
870 | * an intermediate result whose length exceeds PATH_MAX [XPG4.2] | 870 | * an intermediate result whose length exceeds PATH_MAX [XPG4.2] |
871 | */ | 871 | */ |
872 | 872 | ||
873 | static int jfs_symlink(struct inode *dip, struct dentry *dentry, | 873 | static int jfs_symlink(struct inode *dip, struct dentry *dentry, |
874 | const char *name) | 874 | const char *name) |
875 | { | 875 | { |
876 | int rc; | 876 | int rc; |
877 | tid_t tid; | 877 | tid_t tid; |
878 | ino_t ino = 0; | 878 | ino_t ino = 0; |
879 | struct component_name dname; | 879 | struct component_name dname; |
880 | int ssize; /* source pathname size */ | 880 | int ssize; /* source pathname size */ |
881 | struct btstack btstack; | 881 | struct btstack btstack; |
882 | struct inode *ip = dentry->d_inode; | 882 | struct inode *ip = dentry->d_inode; |
883 | unchar *i_fastsymlink; | 883 | unchar *i_fastsymlink; |
884 | s64 xlen = 0; | 884 | s64 xlen = 0; |
885 | int bmask = 0, xsize; | 885 | int bmask = 0, xsize; |
886 | s64 extent = 0, xaddr; | 886 | s64 extent = 0, xaddr; |
887 | struct metapage *mp; | 887 | struct metapage *mp; |
888 | struct super_block *sb; | 888 | struct super_block *sb; |
889 | struct tblock *tblk; | 889 | struct tblock *tblk; |
890 | 890 | ||
891 | struct inode *iplist[2]; | 891 | struct inode *iplist[2]; |
892 | 892 | ||
893 | jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name); | 893 | jfs_info("jfs_symlink: dip:0x%p name:%s", dip, name); |
894 | 894 | ||
895 | ssize = strlen(name) + 1; | 895 | ssize = strlen(name) + 1; |
896 | 896 | ||
897 | /* | 897 | /* |
898 | * search parent directory for entry/freespace | 898 | * search parent directory for entry/freespace |
899 | * (dtSearch() returns parent directory page pinned) | 899 | * (dtSearch() returns parent directory page pinned) |
900 | */ | 900 | */ |
901 | 901 | ||
902 | if ((rc = get_UCSname(&dname, dentry))) | 902 | if ((rc = get_UCSname(&dname, dentry))) |
903 | goto out1; | 903 | goto out1; |
904 | 904 | ||
905 | /* | 905 | /* |
906 | * allocate on-disk/in-memory inode for symbolic link: | 906 | * allocate on-disk/in-memory inode for symbolic link: |
907 | * (iAlloc() returns new, locked inode) | 907 | * (iAlloc() returns new, locked inode) |
908 | */ | 908 | */ |
909 | ip = ialloc(dip, S_IFLNK | 0777); | 909 | ip = ialloc(dip, S_IFLNK | 0777); |
910 | if (IS_ERR(ip)) { | 910 | if (IS_ERR(ip)) { |
911 | rc = PTR_ERR(ip); | 911 | rc = PTR_ERR(ip); |
912 | goto out2; | 912 | goto out2; |
913 | } | 913 | } |
914 | 914 | ||
915 | tid = txBegin(dip->i_sb, 0); | 915 | tid = txBegin(dip->i_sb, 0); |
916 | 916 | ||
917 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); | 917 | mutex_lock_nested(&JFS_IP(dip)->commit_mutex, COMMIT_MUTEX_PARENT); |
918 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 918 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
919 | 919 | ||
920 | rc = jfs_init_security(tid, ip, dip); | 920 | rc = jfs_init_security(tid, ip, dip); |
921 | if (rc) | 921 | if (rc) |
922 | goto out3; | 922 | goto out3; |
923 | 923 | ||
924 | tblk = tid_to_tblock(tid); | 924 | tblk = tid_to_tblock(tid); |
925 | tblk->xflag |= COMMIT_CREATE; | 925 | tblk->xflag |= COMMIT_CREATE; |
926 | tblk->ino = ip->i_ino; | 926 | tblk->ino = ip->i_ino; |
927 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; | 927 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; |
928 | 928 | ||
929 | /* fix symlink access permission | 929 | /* fix symlink access permission |
930 | * (dir_create() ANDs in the u.u_cmask, | 930 | * (dir_create() ANDs in the u.u_cmask, |
931 | * but symlinks really need to be 777 access) | 931 | * but symlinks really need to be 777 access) |
932 | */ | 932 | */ |
933 | ip->i_mode |= 0777; | 933 | ip->i_mode |= 0777; |
934 | 934 | ||
935 | /* | 935 | /* |
936 | * write symbolic link target path name | 936 | * write symbolic link target path name |
937 | */ | 937 | */ |
938 | xtInitRoot(tid, ip); | 938 | xtInitRoot(tid, ip); |
939 | 939 | ||
940 | /* | 940 | /* |
941 | * write source path name inline in on-disk inode (fast symbolic link) | 941 | * write source path name inline in on-disk inode (fast symbolic link) |
942 | */ | 942 | */ |
943 | 943 | ||
944 | if (ssize <= IDATASIZE) { | 944 | if (ssize <= IDATASIZE) { |
945 | ip->i_op = &jfs_symlink_inode_operations; | 945 | ip->i_op = &jfs_symlink_inode_operations; |
946 | 946 | ||
947 | i_fastsymlink = JFS_IP(ip)->i_inline; | 947 | i_fastsymlink = JFS_IP(ip)->i_inline; |
948 | memcpy(i_fastsymlink, name, ssize); | 948 | memcpy(i_fastsymlink, name, ssize); |
949 | ip->i_size = ssize - 1; | 949 | ip->i_size = ssize - 1; |
950 | 950 | ||
951 | /* | 951 | /* |
952 | * if symlink is > 128 bytes, we don't have the space to | 952 | * if symlink is > 128 bytes, we don't have the space to |
953 | * store inline extended attributes | 953 | * store inline extended attributes |
954 | */ | 954 | */ |
955 | if (ssize > sizeof (JFS_IP(ip)->i_inline)) | 955 | if (ssize > sizeof (JFS_IP(ip)->i_inline)) |
956 | JFS_IP(ip)->mode2 &= ~INLINEEA; | 956 | JFS_IP(ip)->mode2 &= ~INLINEEA; |
957 | 957 | ||
958 | jfs_info("jfs_symlink: fast symlink added ssize:%d name:%s ", | 958 | jfs_info("jfs_symlink: fast symlink added ssize:%d name:%s ", |
959 | ssize, name); | 959 | ssize, name); |
960 | } | 960 | } |
961 | /* | 961 | /* |
962 | * write source path name in a single extent | 962 | * write source path name in a single extent |
963 | */ | 963 | */ |
964 | else { | 964 | else { |
965 | jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); | 965 | jfs_info("jfs_symlink: allocate extent ip:0x%p", ip); |
966 | 966 | ||
967 | ip->i_op = &page_symlink_inode_operations; | 967 | ip->i_op = &page_symlink_inode_operations; |
968 | ip->i_mapping->a_ops = &jfs_aops; | 968 | ip->i_mapping->a_ops = &jfs_aops; |
969 | 969 | ||
970 | /* | 970 | /* |
971 | * even though the data of symlink object (source | 971 | * even though the data of symlink object (source |
972 | * path name) is treated as non-journaled user data, | 972 | * path name) is treated as non-journaled user data, |
973 | * it is read/written thru buffer cache for performance. | 973 | * it is read/written thru buffer cache for performance. |
974 | */ | 974 | */ |
975 | sb = ip->i_sb; | 975 | sb = ip->i_sb; |
976 | bmask = JFS_SBI(sb)->bsize - 1; | 976 | bmask = JFS_SBI(sb)->bsize - 1; |
977 | xsize = (ssize + bmask) & ~bmask; | 977 | xsize = (ssize + bmask) & ~bmask; |
978 | xaddr = 0; | 978 | xaddr = 0; |
979 | xlen = xsize >> JFS_SBI(sb)->l2bsize; | 979 | xlen = xsize >> JFS_SBI(sb)->l2bsize; |
980 | if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) { | 980 | if ((rc = xtInsert(tid, ip, 0, 0, xlen, &xaddr, 0))) { |
981 | txAbort(tid, 0); | 981 | txAbort(tid, 0); |
982 | goto out3; | 982 | goto out3; |
983 | } | 983 | } |
984 | extent = xaddr; | 984 | extent = xaddr; |
985 | ip->i_size = ssize - 1; | 985 | ip->i_size = ssize - 1; |
986 | while (ssize) { | 986 | while (ssize) { |
987 | /* This is kind of silly since PATH_MAX == 4K */ | 987 | /* This is kind of silly since PATH_MAX == 4K */ |
988 | int copy_size = min(ssize, PSIZE); | 988 | int copy_size = min(ssize, PSIZE); |
989 | 989 | ||
990 | mp = get_metapage(ip, xaddr, PSIZE, 1); | 990 | mp = get_metapage(ip, xaddr, PSIZE, 1); |
991 | 991 | ||
992 | if (mp == NULL) { | 992 | if (mp == NULL) { |
993 | xtTruncate(tid, ip, 0, COMMIT_PWMAP); | 993 | xtTruncate(tid, ip, 0, COMMIT_PWMAP); |
994 | rc = -EIO; | 994 | rc = -EIO; |
995 | txAbort(tid, 0); | 995 | txAbort(tid, 0); |
996 | goto out3; | 996 | goto out3; |
997 | } | 997 | } |
998 | memcpy(mp->data, name, copy_size); | 998 | memcpy(mp->data, name, copy_size); |
999 | flush_metapage(mp); | 999 | flush_metapage(mp); |
1000 | ssize -= copy_size; | 1000 | ssize -= copy_size; |
1001 | name += copy_size; | 1001 | name += copy_size; |
1002 | xaddr += JFS_SBI(sb)->nbperpage; | 1002 | xaddr += JFS_SBI(sb)->nbperpage; |
1003 | } | 1003 | } |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | /* | 1006 | /* |
1007 | * create entry for symbolic link in parent directory | 1007 | * create entry for symbolic link in parent directory |
1008 | */ | 1008 | */ |
1009 | rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE); | 1009 | rc = dtSearch(dip, &dname, &ino, &btstack, JFS_CREATE); |
1010 | if (rc == 0) { | 1010 | if (rc == 0) { |
1011 | ino = ip->i_ino; | 1011 | ino = ip->i_ino; |
1012 | rc = dtInsert(tid, dip, &dname, &ino, &btstack); | 1012 | rc = dtInsert(tid, dip, &dname, &ino, &btstack); |
1013 | } | 1013 | } |
1014 | if (rc) { | 1014 | if (rc) { |
1015 | if (xlen) | 1015 | if (xlen) |
1016 | xtTruncate(tid, ip, 0, COMMIT_PWMAP); | 1016 | xtTruncate(tid, ip, 0, COMMIT_PWMAP); |
1017 | txAbort(tid, 0); | 1017 | txAbort(tid, 0); |
1018 | /* discard new inode */ | 1018 | /* discard new inode */ |
1019 | goto out3; | 1019 | goto out3; |
1020 | } | 1020 | } |
1021 | 1021 | ||
1022 | insert_inode_hash(ip); | 1022 | insert_inode_hash(ip); |
1023 | mark_inode_dirty(ip); | 1023 | mark_inode_dirty(ip); |
1024 | 1024 | ||
1025 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; | 1025 | dip->i_ctime = dip->i_mtime = CURRENT_TIME; |
1026 | mark_inode_dirty(dip); | 1026 | mark_inode_dirty(dip); |
1027 | /* | 1027 | /* |
1028 | * commit update of parent directory and link object | 1028 | * commit update of parent directory and link object |
1029 | */ | 1029 | */ |
1030 | 1030 | ||
1031 | iplist[0] = dip; | 1031 | iplist[0] = dip; |
1032 | iplist[1] = ip; | 1032 | iplist[1] = ip; |
1033 | rc = txCommit(tid, 2, &iplist[0], 0); | 1033 | rc = txCommit(tid, 2, &iplist[0], 0); |
1034 | 1034 | ||
1035 | out3: | 1035 | out3: |
1036 | txEnd(tid); | 1036 | txEnd(tid); |
1037 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 1037 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
1038 | mutex_unlock(&JFS_IP(dip)->commit_mutex); | 1038 | mutex_unlock(&JFS_IP(dip)->commit_mutex); |
1039 | if (rc) { | 1039 | if (rc) { |
1040 | free_ea_wmap(ip); | 1040 | free_ea_wmap(ip); |
1041 | ip->i_nlink = 0; | 1041 | ip->i_nlink = 0; |
1042 | iput(ip); | 1042 | iput(ip); |
1043 | } else | 1043 | } else |
1044 | d_instantiate(dentry, ip); | 1044 | d_instantiate(dentry, ip); |
1045 | 1045 | ||
1046 | out2: | 1046 | out2: |
1047 | free_UCSname(&dname); | 1047 | free_UCSname(&dname); |
1048 | 1048 | ||
1049 | out1: | 1049 | out1: |
1050 | jfs_info("jfs_symlink: rc:%d", rc); | 1050 | jfs_info("jfs_symlink: rc:%d", rc); |
1051 | return rc; | 1051 | return rc; |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | 1054 | ||
1055 | /* | 1055 | /* |
1056 | * NAME: jfs_rename | 1056 | * NAME: jfs_rename |
1057 | * | 1057 | * |
1058 | * FUNCTION: rename a file or directory | 1058 | * FUNCTION: rename a file or directory |
1059 | */ | 1059 | */ |
1060 | static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 1060 | static int jfs_rename(struct inode *old_dir, struct dentry *old_dentry, |
1061 | struct inode *new_dir, struct dentry *new_dentry) | 1061 | struct inode *new_dir, struct dentry *new_dentry) |
1062 | { | 1062 | { |
1063 | struct btstack btstack; | 1063 | struct btstack btstack; |
1064 | ino_t ino; | 1064 | ino_t ino; |
1065 | struct component_name new_dname; | 1065 | struct component_name new_dname; |
1066 | struct inode *new_ip; | 1066 | struct inode *new_ip; |
1067 | struct component_name old_dname; | 1067 | struct component_name old_dname; |
1068 | struct inode *old_ip; | 1068 | struct inode *old_ip; |
1069 | int rc; | 1069 | int rc; |
1070 | tid_t tid; | 1070 | tid_t tid; |
1071 | struct tlock *tlck; | 1071 | struct tlock *tlck; |
1072 | struct dt_lock *dtlck; | 1072 | struct dt_lock *dtlck; |
1073 | struct lv *lv; | 1073 | struct lv *lv; |
1074 | int ipcount; | 1074 | int ipcount; |
1075 | struct inode *iplist[4]; | 1075 | struct inode *iplist[4]; |
1076 | struct tblock *tblk; | 1076 | struct tblock *tblk; |
1077 | s64 new_size = 0; | 1077 | s64 new_size = 0; |
1078 | int commit_flag; | 1078 | int commit_flag; |
1079 | 1079 | ||
1080 | 1080 | ||
1081 | jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, | 1081 | jfs_info("jfs_rename: %s %s", old_dentry->d_name.name, |
1082 | new_dentry->d_name.name); | 1082 | new_dentry->d_name.name); |
1083 | 1083 | ||
1084 | old_ip = old_dentry->d_inode; | 1084 | old_ip = old_dentry->d_inode; |
1085 | new_ip = new_dentry->d_inode; | 1085 | new_ip = new_dentry->d_inode; |
1086 | 1086 | ||
1087 | if ((rc = get_UCSname(&old_dname, old_dentry))) | 1087 | if ((rc = get_UCSname(&old_dname, old_dentry))) |
1088 | goto out1; | 1088 | goto out1; |
1089 | 1089 | ||
1090 | if ((rc = get_UCSname(&new_dname, new_dentry))) | 1090 | if ((rc = get_UCSname(&new_dname, new_dentry))) |
1091 | goto out2; | 1091 | goto out2; |
1092 | 1092 | ||
1093 | /* | 1093 | /* |
1094 | * Make sure source inode number is what we think it is | 1094 | * Make sure source inode number is what we think it is |
1095 | */ | 1095 | */ |
1096 | rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP); | 1096 | rc = dtSearch(old_dir, &old_dname, &ino, &btstack, JFS_LOOKUP); |
1097 | if (rc || (ino != old_ip->i_ino)) { | 1097 | if (rc || (ino != old_ip->i_ino)) { |
1098 | rc = -ENOENT; | 1098 | rc = -ENOENT; |
1099 | goto out3; | 1099 | goto out3; |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | /* | 1102 | /* |
1103 | * Make sure dest inode number (if any) is what we think it is | 1103 | * Make sure dest inode number (if any) is what we think it is |
1104 | */ | 1104 | */ |
1105 | rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP); | 1105 | rc = dtSearch(new_dir, &new_dname, &ino, &btstack, JFS_LOOKUP); |
1106 | if (!rc) { | 1106 | if (!rc) { |
1107 | if ((!new_ip) || (ino != new_ip->i_ino)) { | 1107 | if ((!new_ip) || (ino != new_ip->i_ino)) { |
1108 | rc = -ESTALE; | 1108 | rc = -ESTALE; |
1109 | goto out3; | 1109 | goto out3; |
1110 | } | 1110 | } |
1111 | } else if (rc != -ENOENT) | 1111 | } else if (rc != -ENOENT) |
1112 | goto out3; | 1112 | goto out3; |
1113 | else if (new_ip) { | 1113 | else if (new_ip) { |
1114 | /* no entry exists, but one was expected */ | 1114 | /* no entry exists, but one was expected */ |
1115 | rc = -ESTALE; | 1115 | rc = -ESTALE; |
1116 | goto out3; | 1116 | goto out3; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | if (S_ISDIR(old_ip->i_mode)) { | 1119 | if (S_ISDIR(old_ip->i_mode)) { |
1120 | if (new_ip) { | 1120 | if (new_ip) { |
1121 | if (!dtEmpty(new_ip)) { | 1121 | if (!dtEmpty(new_ip)) { |
1122 | rc = -ENOTEMPTY; | 1122 | rc = -ENOTEMPTY; |
1123 | goto out3; | 1123 | goto out3; |
1124 | } | 1124 | } |
1125 | } else if ((new_dir != old_dir) && | 1125 | } else if ((new_dir != old_dir) && |
1126 | (new_dir->i_nlink == JFS_LINK_MAX)) { | 1126 | (new_dir->i_nlink == JFS_LINK_MAX)) { |
1127 | rc = -EMLINK; | 1127 | rc = -EMLINK; |
1128 | goto out3; | 1128 | goto out3; |
1129 | } | 1129 | } |
1130 | } else if (new_ip) { | 1130 | } else if (new_ip) { |
1131 | IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); | 1131 | IWRITE_LOCK(new_ip, RDWRLOCK_NORMAL); |
1132 | /* Init inode for quota operations. */ | 1132 | /* Init inode for quota operations. */ |
1133 | DQUOT_INIT(new_ip); | 1133 | DQUOT_INIT(new_ip); |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | /* | 1136 | /* |
1137 | * The real work starts here | 1137 | * The real work starts here |
1138 | */ | 1138 | */ |
1139 | tid = txBegin(new_dir->i_sb, 0); | 1139 | tid = txBegin(new_dir->i_sb, 0); |
1140 | 1140 | ||
1141 | /* | 1141 | /* |
1142 | * How do we know the locking is safe from deadlocks? | 1142 | * How do we know the locking is safe from deadlocks? |
1143 | * The vfs does the hard part for us. Any time we are taking nested | 1143 | * The vfs does the hard part for us. Any time we are taking nested |
1144 | * commit_mutexes, the vfs already has i_mutex held on the parent. | 1144 | * commit_mutexes, the vfs already has i_mutex held on the parent. |
1145 | * Here, the vfs has already taken i_mutex on both old_dir and new_dir. | 1145 | * Here, the vfs has already taken i_mutex on both old_dir and new_dir. |
1146 | */ | 1146 | */ |
1147 | mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT); | 1147 | mutex_lock_nested(&JFS_IP(new_dir)->commit_mutex, COMMIT_MUTEX_PARENT); |
1148 | mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 1148 | mutex_lock_nested(&JFS_IP(old_ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
1149 | if (old_dir != new_dir) | 1149 | if (old_dir != new_dir) |
1150 | mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex, | 1150 | mutex_lock_nested(&JFS_IP(old_dir)->commit_mutex, |
1151 | COMMIT_MUTEX_SECOND_PARENT); | 1151 | COMMIT_MUTEX_SECOND_PARENT); |
1152 | 1152 | ||
1153 | if (new_ip) { | 1153 | if (new_ip) { |
1154 | mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex, | 1154 | mutex_lock_nested(&JFS_IP(new_ip)->commit_mutex, |
1155 | COMMIT_MUTEX_VICTIM); | 1155 | COMMIT_MUTEX_VICTIM); |
1156 | /* | 1156 | /* |
1157 | * Change existing directory entry to new inode number | 1157 | * Change existing directory entry to new inode number |
1158 | */ | 1158 | */ |
1159 | ino = new_ip->i_ino; | 1159 | ino = new_ip->i_ino; |
1160 | rc = dtModify(tid, new_dir, &new_dname, &ino, | 1160 | rc = dtModify(tid, new_dir, &new_dname, &ino, |
1161 | old_ip->i_ino, JFS_RENAME); | 1161 | old_ip->i_ino, JFS_RENAME); |
1162 | if (rc) | 1162 | if (rc) |
1163 | goto out4; | 1163 | goto out4; |
1164 | drop_nlink(new_ip); | 1164 | drop_nlink(new_ip); |
1165 | if (S_ISDIR(new_ip->i_mode)) { | 1165 | if (S_ISDIR(new_ip->i_mode)) { |
1166 | drop_nlink(new_ip); | 1166 | drop_nlink(new_ip); |
1167 | if (new_ip->i_nlink) { | 1167 | if (new_ip->i_nlink) { |
1168 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); | 1168 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); |
1169 | if (old_dir != new_dir) | 1169 | if (old_dir != new_dir) |
1170 | mutex_unlock(&JFS_IP(old_dir)->commit_mutex); | 1170 | mutex_unlock(&JFS_IP(old_dir)->commit_mutex); |
1171 | mutex_unlock(&JFS_IP(old_ip)->commit_mutex); | 1171 | mutex_unlock(&JFS_IP(old_ip)->commit_mutex); |
1172 | mutex_unlock(&JFS_IP(new_dir)->commit_mutex); | 1172 | mutex_unlock(&JFS_IP(new_dir)->commit_mutex); |
1173 | if (!S_ISDIR(old_ip->i_mode) && new_ip) | 1173 | if (!S_ISDIR(old_ip->i_mode) && new_ip) |
1174 | IWRITE_UNLOCK(new_ip); | 1174 | IWRITE_UNLOCK(new_ip); |
1175 | jfs_error(new_ip->i_sb, | 1175 | jfs_error(new_ip->i_sb, |
1176 | "jfs_rename: new_ip->i_nlink != 0"); | 1176 | "jfs_rename: new_ip->i_nlink != 0"); |
1177 | return -EIO; | 1177 | return -EIO; |
1178 | } | 1178 | } |
1179 | tblk = tid_to_tblock(tid); | 1179 | tblk = tid_to_tblock(tid); |
1180 | tblk->xflag |= COMMIT_DELETE; | 1180 | tblk->xflag |= COMMIT_DELETE; |
1181 | tblk->u.ip = new_ip; | 1181 | tblk->u.ip = new_ip; |
1182 | } else if (new_ip->i_nlink == 0) { | 1182 | } else if (new_ip->i_nlink == 0) { |
1183 | assert(!test_cflag(COMMIT_Nolink, new_ip)); | 1183 | assert(!test_cflag(COMMIT_Nolink, new_ip)); |
1184 | /* free block resources */ | 1184 | /* free block resources */ |
1185 | if ((new_size = commitZeroLink(tid, new_ip)) < 0) { | 1185 | if ((new_size = commitZeroLink(tid, new_ip)) < 0) { |
1186 | txAbort(tid, 1); /* Marks FS Dirty */ | 1186 | txAbort(tid, 1); /* Marks FS Dirty */ |
1187 | rc = new_size; | 1187 | rc = new_size; |
1188 | goto out4; | 1188 | goto out4; |
1189 | } | 1189 | } |
1190 | tblk = tid_to_tblock(tid); | 1190 | tblk = tid_to_tblock(tid); |
1191 | tblk->xflag |= COMMIT_DELETE; | 1191 | tblk->xflag |= COMMIT_DELETE; |
1192 | tblk->u.ip = new_ip; | 1192 | tblk->u.ip = new_ip; |
1193 | } else { | 1193 | } else { |
1194 | new_ip->i_ctime = CURRENT_TIME; | 1194 | new_ip->i_ctime = CURRENT_TIME; |
1195 | mark_inode_dirty(new_ip); | 1195 | mark_inode_dirty(new_ip); |
1196 | } | 1196 | } |
1197 | } else { | 1197 | } else { |
1198 | /* | 1198 | /* |
1199 | * Add new directory entry | 1199 | * Add new directory entry |
1200 | */ | 1200 | */ |
1201 | rc = dtSearch(new_dir, &new_dname, &ino, &btstack, | 1201 | rc = dtSearch(new_dir, &new_dname, &ino, &btstack, |
1202 | JFS_CREATE); | 1202 | JFS_CREATE); |
1203 | if (rc) { | 1203 | if (rc) { |
1204 | jfs_err("jfs_rename didn't expect dtSearch to fail " | 1204 | jfs_err("jfs_rename didn't expect dtSearch to fail " |
1205 | "w/rc = %d", rc); | 1205 | "w/rc = %d", rc); |
1206 | goto out4; | 1206 | goto out4; |
1207 | } | 1207 | } |
1208 | 1208 | ||
1209 | ino = old_ip->i_ino; | 1209 | ino = old_ip->i_ino; |
1210 | rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack); | 1210 | rc = dtInsert(tid, new_dir, &new_dname, &ino, &btstack); |
1211 | if (rc) { | 1211 | if (rc) { |
1212 | if (rc == -EIO) | 1212 | if (rc == -EIO) |
1213 | jfs_err("jfs_rename: dtInsert returned -EIO"); | 1213 | jfs_err("jfs_rename: dtInsert returned -EIO"); |
1214 | goto out4; | 1214 | goto out4; |
1215 | } | 1215 | } |
1216 | if (S_ISDIR(old_ip->i_mode)) | 1216 | if (S_ISDIR(old_ip->i_mode)) |
1217 | inc_nlink(new_dir); | 1217 | inc_nlink(new_dir); |
1218 | } | 1218 | } |
1219 | /* | 1219 | /* |
1220 | * Remove old directory entry | 1220 | * Remove old directory entry |
1221 | */ | 1221 | */ |
1222 | 1222 | ||
1223 | ino = old_ip->i_ino; | 1223 | ino = old_ip->i_ino; |
1224 | rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE); | 1224 | rc = dtDelete(tid, old_dir, &old_dname, &ino, JFS_REMOVE); |
1225 | if (rc) { | 1225 | if (rc) { |
1226 | jfs_err("jfs_rename did not expect dtDelete to return rc = %d", | 1226 | jfs_err("jfs_rename did not expect dtDelete to return rc = %d", |
1227 | rc); | 1227 | rc); |
1228 | txAbort(tid, 1); /* Marks Filesystem dirty */ | 1228 | txAbort(tid, 1); /* Marks Filesystem dirty */ |
1229 | goto out4; | 1229 | goto out4; |
1230 | } | 1230 | } |
1231 | if (S_ISDIR(old_ip->i_mode)) { | 1231 | if (S_ISDIR(old_ip->i_mode)) { |
1232 | drop_nlink(old_dir); | 1232 | drop_nlink(old_dir); |
1233 | if (old_dir != new_dir) { | 1233 | if (old_dir != new_dir) { |
1234 | /* | 1234 | /* |
1235 | * Change inode number of parent for moved directory | 1235 | * Change inode number of parent for moved directory |
1236 | */ | 1236 | */ |
1237 | 1237 | ||
1238 | JFS_IP(old_ip)->i_dtroot.header.idotdot = | 1238 | JFS_IP(old_ip)->i_dtroot.header.idotdot = |
1239 | cpu_to_le32(new_dir->i_ino); | 1239 | cpu_to_le32(new_dir->i_ino); |
1240 | 1240 | ||
1241 | /* Linelock header of dtree */ | 1241 | /* Linelock header of dtree */ |
1242 | tlck = txLock(tid, old_ip, | 1242 | tlck = txLock(tid, old_ip, |
1243 | (struct metapage *) &JFS_IP(old_ip)->bxflag, | 1243 | (struct metapage *) &JFS_IP(old_ip)->bxflag, |
1244 | tlckDTREE | tlckBTROOT | tlckRELINK); | 1244 | tlckDTREE | tlckBTROOT | tlckRELINK); |
1245 | dtlck = (struct dt_lock *) & tlck->lock; | 1245 | dtlck = (struct dt_lock *) & tlck->lock; |
1246 | ASSERT(dtlck->index == 0); | 1246 | ASSERT(dtlck->index == 0); |
1247 | lv = & dtlck->lv[0]; | 1247 | lv = & dtlck->lv[0]; |
1248 | lv->offset = 0; | 1248 | lv->offset = 0; |
1249 | lv->length = 1; | 1249 | lv->length = 1; |
1250 | dtlck->index++; | 1250 | dtlck->index++; |
1251 | } | 1251 | } |
1252 | } | 1252 | } |
1253 | 1253 | ||
1254 | /* | 1254 | /* |
1255 | * Update ctime on changed/moved inodes & mark dirty | 1255 | * Update ctime on changed/moved inodes & mark dirty |
1256 | */ | 1256 | */ |
1257 | old_ip->i_ctime = CURRENT_TIME; | 1257 | old_ip->i_ctime = CURRENT_TIME; |
1258 | mark_inode_dirty(old_ip); | 1258 | mark_inode_dirty(old_ip); |
1259 | 1259 | ||
1260 | new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb); | 1260 | new_dir->i_ctime = new_dir->i_mtime = current_fs_time(new_dir->i_sb); |
1261 | mark_inode_dirty(new_dir); | 1261 | mark_inode_dirty(new_dir); |
1262 | 1262 | ||
1263 | /* Build list of inodes modified by this transaction */ | 1263 | /* Build list of inodes modified by this transaction */ |
1264 | ipcount = 0; | 1264 | ipcount = 0; |
1265 | iplist[ipcount++] = old_ip; | 1265 | iplist[ipcount++] = old_ip; |
1266 | if (new_ip) | 1266 | if (new_ip) |
1267 | iplist[ipcount++] = new_ip; | 1267 | iplist[ipcount++] = new_ip; |
1268 | iplist[ipcount++] = old_dir; | 1268 | iplist[ipcount++] = old_dir; |
1269 | 1269 | ||
1270 | if (old_dir != new_dir) { | 1270 | if (old_dir != new_dir) { |
1271 | iplist[ipcount++] = new_dir; | 1271 | iplist[ipcount++] = new_dir; |
1272 | old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; | 1272 | old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME; |
1273 | mark_inode_dirty(old_dir); | 1273 | mark_inode_dirty(old_dir); |
1274 | } | 1274 | } |
1275 | 1275 | ||
1276 | /* | 1276 | /* |
1277 | * Incomplete truncate of file data can | 1277 | * Incomplete truncate of file data can |
1278 | * result in timing problems unless we synchronously commit the | 1278 | * result in timing problems unless we synchronously commit the |
1279 | * transaction. | 1279 | * transaction. |
1280 | */ | 1280 | */ |
1281 | if (new_size) | 1281 | if (new_size) |
1282 | commit_flag = COMMIT_SYNC; | 1282 | commit_flag = COMMIT_SYNC; |
1283 | else | 1283 | else |
1284 | commit_flag = 0; | 1284 | commit_flag = 0; |
1285 | 1285 | ||
1286 | rc = txCommit(tid, ipcount, iplist, commit_flag); | 1286 | rc = txCommit(tid, ipcount, iplist, commit_flag); |
1287 | 1287 | ||
1288 | out4: | 1288 | out4: |
1289 | txEnd(tid); | 1289 | txEnd(tid); |
1290 | if (new_ip) | 1290 | if (new_ip) |
1291 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); | 1291 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); |
1292 | if (old_dir != new_dir) | 1292 | if (old_dir != new_dir) |
1293 | mutex_unlock(&JFS_IP(old_dir)->commit_mutex); | 1293 | mutex_unlock(&JFS_IP(old_dir)->commit_mutex); |
1294 | mutex_unlock(&JFS_IP(old_ip)->commit_mutex); | 1294 | mutex_unlock(&JFS_IP(old_ip)->commit_mutex); |
1295 | mutex_unlock(&JFS_IP(new_dir)->commit_mutex); | 1295 | mutex_unlock(&JFS_IP(new_dir)->commit_mutex); |
1296 | 1296 | ||
1297 | while (new_size && (rc == 0)) { | 1297 | while (new_size && (rc == 0)) { |
1298 | tid = txBegin(new_ip->i_sb, 0); | 1298 | tid = txBegin(new_ip->i_sb, 0); |
1299 | mutex_lock(&JFS_IP(new_ip)->commit_mutex); | 1299 | mutex_lock(&JFS_IP(new_ip)->commit_mutex); |
1300 | new_size = xtTruncate_pmap(tid, new_ip, new_size); | 1300 | new_size = xtTruncate_pmap(tid, new_ip, new_size); |
1301 | if (new_size < 0) { | 1301 | if (new_size < 0) { |
1302 | txAbort(tid, 1); | 1302 | txAbort(tid, 1); |
1303 | rc = new_size; | 1303 | rc = new_size; |
1304 | } else | 1304 | } else |
1305 | rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC); | 1305 | rc = txCommit(tid, 1, &new_ip, COMMIT_SYNC); |
1306 | txEnd(tid); | 1306 | txEnd(tid); |
1307 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); | 1307 | mutex_unlock(&JFS_IP(new_ip)->commit_mutex); |
1308 | } | 1308 | } |
1309 | if (new_ip && (new_ip->i_nlink == 0)) | 1309 | if (new_ip && (new_ip->i_nlink == 0)) |
1310 | set_cflag(COMMIT_Nolink, new_ip); | 1310 | set_cflag(COMMIT_Nolink, new_ip); |
1311 | out3: | 1311 | out3: |
1312 | free_UCSname(&new_dname); | 1312 | free_UCSname(&new_dname); |
1313 | out2: | 1313 | out2: |
1314 | free_UCSname(&old_dname); | 1314 | free_UCSname(&old_dname); |
1315 | out1: | 1315 | out1: |
1316 | if (new_ip && !S_ISDIR(new_ip->i_mode)) | 1316 | if (new_ip && !S_ISDIR(new_ip->i_mode)) |
1317 | IWRITE_UNLOCK(new_ip); | 1317 | IWRITE_UNLOCK(new_ip); |
1318 | /* | 1318 | /* |
1319 | * Truncating the directory index table is not guaranteed. It | 1319 | * Truncating the directory index table is not guaranteed. It |
1320 | * may need to be done iteratively | 1320 | * may need to be done iteratively |
1321 | */ | 1321 | */ |
1322 | if (test_cflag(COMMIT_Stale, old_dir)) { | 1322 | if (test_cflag(COMMIT_Stale, old_dir)) { |
1323 | if (old_dir->i_size > 1) | 1323 | if (old_dir->i_size > 1) |
1324 | jfs_truncate_nolock(old_dir, 0); | 1324 | jfs_truncate_nolock(old_dir, 0); |
1325 | 1325 | ||
1326 | clear_cflag(COMMIT_Stale, old_dir); | 1326 | clear_cflag(COMMIT_Stale, old_dir); |
1327 | } | 1327 | } |
1328 | 1328 | ||
1329 | jfs_info("jfs_rename: returning %d", rc); | 1329 | jfs_info("jfs_rename: returning %d", rc); |
1330 | return rc; | 1330 | return rc; |
1331 | } | 1331 | } |
1332 | 1332 | ||
1333 | 1333 | ||
1334 | /* | 1334 | /* |
1335 | * NAME: jfs_mknod | 1335 | * NAME: jfs_mknod |
1336 | * | 1336 | * |
1337 | * FUNCTION: Create a special file (device) | 1337 | * FUNCTION: Create a special file (device) |
1338 | */ | 1338 | */ |
1339 | static int jfs_mknod(struct inode *dir, struct dentry *dentry, | 1339 | static int jfs_mknod(struct inode *dir, struct dentry *dentry, |
1340 | int mode, dev_t rdev) | 1340 | int mode, dev_t rdev) |
1341 | { | 1341 | { |
1342 | struct jfs_inode_info *jfs_ip; | 1342 | struct jfs_inode_info *jfs_ip; |
1343 | struct btstack btstack; | 1343 | struct btstack btstack; |
1344 | struct component_name dname; | 1344 | struct component_name dname; |
1345 | ino_t ino; | 1345 | ino_t ino; |
1346 | struct inode *ip; | 1346 | struct inode *ip; |
1347 | struct inode *iplist[2]; | 1347 | struct inode *iplist[2]; |
1348 | int rc; | 1348 | int rc; |
1349 | tid_t tid; | 1349 | tid_t tid; |
1350 | struct tblock *tblk; | 1350 | struct tblock *tblk; |
1351 | 1351 | ||
1352 | if (!new_valid_dev(rdev)) | 1352 | if (!new_valid_dev(rdev)) |
1353 | return -EINVAL; | 1353 | return -EINVAL; |
1354 | 1354 | ||
1355 | jfs_info("jfs_mknod: %s", dentry->d_name.name); | 1355 | jfs_info("jfs_mknod: %s", dentry->d_name.name); |
1356 | 1356 | ||
1357 | if ((rc = get_UCSname(&dname, dentry))) | 1357 | if ((rc = get_UCSname(&dname, dentry))) |
1358 | goto out; | 1358 | goto out; |
1359 | 1359 | ||
1360 | ip = ialloc(dir, mode); | 1360 | ip = ialloc(dir, mode); |
1361 | if (IS_ERR(ip)) { | 1361 | if (IS_ERR(ip)) { |
1362 | rc = PTR_ERR(ip); | 1362 | rc = PTR_ERR(ip); |
1363 | goto out1; | 1363 | goto out1; |
1364 | } | 1364 | } |
1365 | jfs_ip = JFS_IP(ip); | 1365 | jfs_ip = JFS_IP(ip); |
1366 | 1366 | ||
1367 | tid = txBegin(dir->i_sb, 0); | 1367 | tid = txBegin(dir->i_sb, 0); |
1368 | 1368 | ||
1369 | mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); | 1369 | mutex_lock_nested(&JFS_IP(dir)->commit_mutex, COMMIT_MUTEX_PARENT); |
1370 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); | 1370 | mutex_lock_nested(&JFS_IP(ip)->commit_mutex, COMMIT_MUTEX_CHILD); |
1371 | 1371 | ||
1372 | rc = jfs_init_acl(tid, ip, dir); | 1372 | rc = jfs_init_acl(tid, ip, dir); |
1373 | if (rc) | 1373 | if (rc) |
1374 | goto out3; | 1374 | goto out3; |
1375 | 1375 | ||
1376 | rc = jfs_init_security(tid, ip, dir); | 1376 | rc = jfs_init_security(tid, ip, dir); |
1377 | if (rc) { | 1377 | if (rc) { |
1378 | txAbort(tid, 0); | 1378 | txAbort(tid, 0); |
1379 | goto out3; | 1379 | goto out3; |
1380 | } | 1380 | } |
1381 | 1381 | ||
1382 | if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) { | 1382 | if ((rc = dtSearch(dir, &dname, &ino, &btstack, JFS_CREATE))) { |
1383 | txAbort(tid, 0); | 1383 | txAbort(tid, 0); |
1384 | goto out3; | 1384 | goto out3; |
1385 | } | 1385 | } |
1386 | 1386 | ||
1387 | tblk = tid_to_tblock(tid); | 1387 | tblk = tid_to_tblock(tid); |
1388 | tblk->xflag |= COMMIT_CREATE; | 1388 | tblk->xflag |= COMMIT_CREATE; |
1389 | tblk->ino = ip->i_ino; | 1389 | tblk->ino = ip->i_ino; |
1390 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; | 1390 | tblk->u.ixpxd = JFS_IP(ip)->ixpxd; |
1391 | 1391 | ||
1392 | ino = ip->i_ino; | 1392 | ino = ip->i_ino; |
1393 | if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) { | 1393 | if ((rc = dtInsert(tid, dir, &dname, &ino, &btstack))) { |
1394 | txAbort(tid, 0); | 1394 | txAbort(tid, 0); |
1395 | goto out3; | 1395 | goto out3; |
1396 | } | 1396 | } |
1397 | 1397 | ||
1398 | ip->i_op = &jfs_file_inode_operations; | 1398 | ip->i_op = &jfs_file_inode_operations; |
1399 | jfs_ip->dev = new_encode_dev(rdev); | 1399 | jfs_ip->dev = new_encode_dev(rdev); |
1400 | init_special_inode(ip, ip->i_mode, rdev); | 1400 | init_special_inode(ip, ip->i_mode, rdev); |
1401 | 1401 | ||
1402 | insert_inode_hash(ip); | 1402 | insert_inode_hash(ip); |
1403 | mark_inode_dirty(ip); | 1403 | mark_inode_dirty(ip); |
1404 | 1404 | ||
1405 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; | 1405 | dir->i_ctime = dir->i_mtime = CURRENT_TIME; |
1406 | 1406 | ||
1407 | mark_inode_dirty(dir); | 1407 | mark_inode_dirty(dir); |
1408 | 1408 | ||
1409 | iplist[0] = dir; | 1409 | iplist[0] = dir; |
1410 | iplist[1] = ip; | 1410 | iplist[1] = ip; |
1411 | rc = txCommit(tid, 2, iplist, 0); | 1411 | rc = txCommit(tid, 2, iplist, 0); |
1412 | 1412 | ||
1413 | out3: | 1413 | out3: |
1414 | txEnd(tid); | 1414 | txEnd(tid); |
1415 | mutex_unlock(&JFS_IP(ip)->commit_mutex); | 1415 | mutex_unlock(&JFS_IP(ip)->commit_mutex); |
1416 | mutex_unlock(&JFS_IP(dir)->commit_mutex); | 1416 | mutex_unlock(&JFS_IP(dir)->commit_mutex); |
1417 | if (rc) { | 1417 | if (rc) { |
1418 | free_ea_wmap(ip); | 1418 | free_ea_wmap(ip); |
1419 | ip->i_nlink = 0; | 1419 | ip->i_nlink = 0; |
1420 | iput(ip); | 1420 | iput(ip); |
1421 | } else | 1421 | } else |
1422 | d_instantiate(dentry, ip); | 1422 | d_instantiate(dentry, ip); |
1423 | 1423 | ||
1424 | out1: | 1424 | out1: |
1425 | free_UCSname(&dname); | 1425 | free_UCSname(&dname); |
1426 | 1426 | ||
1427 | out: | 1427 | out: |
1428 | jfs_info("jfs_mknod: returning %d", rc); | 1428 | jfs_info("jfs_mknod: returning %d", rc); |
1429 | return rc; | 1429 | return rc; |
1430 | } | 1430 | } |
1431 | 1431 | ||
1432 | static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd) | 1432 | static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd) |
1433 | { | 1433 | { |
1434 | struct btstack btstack; | 1434 | struct btstack btstack; |
1435 | ino_t inum; | 1435 | ino_t inum; |
1436 | struct inode *ip; | 1436 | struct inode *ip; |
1437 | struct component_name key; | 1437 | struct component_name key; |
1438 | const char *name = dentry->d_name.name; | 1438 | const char *name = dentry->d_name.name; |
1439 | int len = dentry->d_name.len; | 1439 | int len = dentry->d_name.len; |
1440 | int rc; | 1440 | int rc; |
1441 | 1441 | ||
1442 | jfs_info("jfs_lookup: name = %s", name); | 1442 | jfs_info("jfs_lookup: name = %s", name); |
1443 | 1443 | ||
1444 | if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2) | 1444 | if (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2) |
1445 | dentry->d_op = &jfs_ci_dentry_operations; | 1445 | dentry->d_op = &jfs_ci_dentry_operations; |
1446 | 1446 | ||
1447 | if ((name[0] == '.') && (len == 1)) | 1447 | if ((name[0] == '.') && (len == 1)) |
1448 | inum = dip->i_ino; | 1448 | inum = dip->i_ino; |
1449 | else if (strcmp(name, "..") == 0) | 1449 | else if (strcmp(name, "..") == 0) |
1450 | inum = PARENT(dip); | 1450 | inum = PARENT(dip); |
1451 | else { | 1451 | else { |
1452 | if ((rc = get_UCSname(&key, dentry))) | 1452 | if ((rc = get_UCSname(&key, dentry))) |
1453 | return ERR_PTR(rc); | 1453 | return ERR_PTR(rc); |
1454 | rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP); | 1454 | rc = dtSearch(dip, &key, &inum, &btstack, JFS_LOOKUP); |
1455 | free_UCSname(&key); | 1455 | free_UCSname(&key); |
1456 | if (rc == -ENOENT) { | 1456 | if (rc == -ENOENT) { |
1457 | d_add(dentry, NULL); | 1457 | d_add(dentry, NULL); |
1458 | return ERR_PTR(0); | 1458 | return ERR_PTR(0); |
1459 | } else if (rc) { | 1459 | } else if (rc) { |
1460 | jfs_err("jfs_lookup: dtSearch returned %d", rc); | 1460 | jfs_err("jfs_lookup: dtSearch returned %d", rc); |
1461 | return ERR_PTR(rc); | 1461 | return ERR_PTR(rc); |
1462 | } | 1462 | } |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | ip = iget(dip->i_sb, inum); | 1465 | ip = jfs_iget(dip->i_sb, inum); |
1466 | if (ip == NULL || is_bad_inode(ip)) { | 1466 | if (IS_ERR(ip)) { |
1467 | jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum); | 1467 | jfs_err("jfs_lookup: iget failed on inum %d", (uint) inum); |
1468 | if (ip) | 1468 | return ERR_CAST(ip); |
1469 | iput(ip); | ||
1470 | return ERR_PTR(-EACCES); | ||
1471 | } | 1469 | } |
1472 | 1470 | ||
1473 | dentry = d_splice_alias(ip, dentry); | 1471 | dentry = d_splice_alias(ip, dentry); |
1474 | 1472 | ||
1475 | if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)) | 1473 | if (dentry && (JFS_SBI(dip->i_sb)->mntflag & JFS_OS2)) |
1476 | dentry->d_op = &jfs_ci_dentry_operations; | 1474 | dentry->d_op = &jfs_ci_dentry_operations; |
1477 | 1475 | ||
1478 | return dentry; | 1476 | return dentry; |
1479 | } | 1477 | } |
1480 | 1478 | ||
1481 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, | 1479 | static struct inode *jfs_nfs_get_inode(struct super_block *sb, |
1482 | u64 ino, u32 generation) | 1480 | u64 ino, u32 generation) |
1483 | { | 1481 | { |
1484 | struct inode *inode; | 1482 | struct inode *inode; |
1485 | 1483 | ||
1486 | if (ino == 0) | 1484 | if (ino == 0) |
1487 | return ERR_PTR(-ESTALE); | 1485 | return ERR_PTR(-ESTALE); |
1488 | inode = iget(sb, ino); | 1486 | inode = jfs_iget(sb, ino); |
1489 | if (inode == NULL) | 1487 | if (IS_ERR(inode)) |
1490 | return ERR_PTR(-ENOMEM); | 1488 | return ERR_CAST(inode); |
1491 | 1489 | ||
1492 | if (is_bad_inode(inode) || | 1490 | if (generation && inode->i_generation != generation) { |
1493 | (generation && inode->i_generation != generation)) { | ||
1494 | iput(inode); | 1491 | iput(inode); |
1495 | return ERR_PTR(-ESTALE); | 1492 | return ERR_PTR(-ESTALE); |
1496 | } | 1493 | } |
1497 | 1494 | ||
1498 | return inode; | 1495 | return inode; |
1499 | } | 1496 | } |
1500 | 1497 | ||
1501 | struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, | 1498 | struct dentry *jfs_fh_to_dentry(struct super_block *sb, struct fid *fid, |
1502 | int fh_len, int fh_type) | 1499 | int fh_len, int fh_type) |
1503 | { | 1500 | { |
1504 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | 1501 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, |
1505 | jfs_nfs_get_inode); | 1502 | jfs_nfs_get_inode); |
1506 | } | 1503 | } |
1507 | 1504 | ||
1508 | struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, | 1505 | struct dentry *jfs_fh_to_parent(struct super_block *sb, struct fid *fid, |
1509 | int fh_len, int fh_type) | 1506 | int fh_len, int fh_type) |
1510 | { | 1507 | { |
1511 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | 1508 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, |
1512 | jfs_nfs_get_inode); | 1509 | jfs_nfs_get_inode); |
1513 | } | 1510 | } |
1514 | 1511 | ||
1515 | struct dentry *jfs_get_parent(struct dentry *dentry) | 1512 | struct dentry *jfs_get_parent(struct dentry *dentry) |
1516 | { | 1513 | { |
1517 | struct super_block *sb = dentry->d_inode->i_sb; | 1514 | struct super_block *sb = dentry->d_inode->i_sb; |
1518 | struct dentry *parent = ERR_PTR(-ENOENT); | 1515 | struct dentry *parent = ERR_PTR(-ENOENT); |
1519 | struct inode *inode; | 1516 | struct inode *inode; |
1520 | unsigned long parent_ino; | 1517 | unsigned long parent_ino; |
1521 | 1518 | ||
1522 | parent_ino = | 1519 | parent_ino = |
1523 | le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot); | 1520 | le32_to_cpu(JFS_IP(dentry->d_inode)->i_dtroot.header.idotdot); |
1524 | inode = iget(sb, parent_ino); | 1521 | inode = jfs_iget(sb, parent_ino); |
1525 | if (inode) { | 1522 | if (IS_ERR(inode)) { |
1526 | if (is_bad_inode(inode)) { | 1523 | parent = ERR_CAST(inode); |
1524 | } else { | ||
1525 | parent = d_alloc_anon(inode); | ||
1526 | if (!parent) { | ||
1527 | parent = ERR_PTR(-ENOMEM); | ||
1527 | iput(inode); | 1528 | iput(inode); |
1528 | parent = ERR_PTR(-EACCES); | ||
1529 | } else { | ||
1530 | parent = d_alloc_anon(inode); | ||
1531 | if (!parent) { | ||
1532 | parent = ERR_PTR(-ENOMEM); | ||
1533 | iput(inode); | ||
1534 | } | ||
1535 | } | 1529 | } |
1536 | } | 1530 | } |
1537 | 1531 | ||
1538 | return parent; | 1532 | return parent; |
1539 | } | 1533 | } |
1540 | 1534 | ||
1541 | const struct inode_operations jfs_dir_inode_operations = { | 1535 | const struct inode_operations jfs_dir_inode_operations = { |
1542 | .create = jfs_create, | 1536 | .create = jfs_create, |
1543 | .lookup = jfs_lookup, | 1537 | .lookup = jfs_lookup, |
1544 | .link = jfs_link, | 1538 | .link = jfs_link, |
1545 | .unlink = jfs_unlink, | 1539 | .unlink = jfs_unlink, |
1546 | .symlink = jfs_symlink, | 1540 | .symlink = jfs_symlink, |
1547 | .mkdir = jfs_mkdir, | 1541 | .mkdir = jfs_mkdir, |
1548 | .rmdir = jfs_rmdir, | 1542 | .rmdir = jfs_rmdir, |
1549 | .mknod = jfs_mknod, | 1543 | .mknod = jfs_mknod, |
1550 | .rename = jfs_rename, | 1544 | .rename = jfs_rename, |
1551 | .setxattr = jfs_setxattr, | 1545 | .setxattr = jfs_setxattr, |
1552 | .getxattr = jfs_getxattr, | 1546 | .getxattr = jfs_getxattr, |
1553 | .listxattr = jfs_listxattr, | 1547 | .listxattr = jfs_listxattr, |
1554 | .removexattr = jfs_removexattr, | 1548 | .removexattr = jfs_removexattr, |
1555 | #ifdef CONFIG_JFS_POSIX_ACL | 1549 | #ifdef CONFIG_JFS_POSIX_ACL |
1556 | .setattr = jfs_setattr, | 1550 | .setattr = jfs_setattr, |
1557 | .permission = jfs_permission, | 1551 | .permission = jfs_permission, |
1558 | #endif | 1552 | #endif |
1559 | }; | 1553 | }; |
1560 | 1554 | ||
1561 | const struct file_operations jfs_dir_operations = { | 1555 | const struct file_operations jfs_dir_operations = { |
1562 | .read = generic_read_dir, | 1556 | .read = generic_read_dir, |
1563 | .readdir = jfs_readdir, | 1557 | .readdir = jfs_readdir, |
1564 | .fsync = jfs_fsync, | 1558 | .fsync = jfs_fsync, |
1565 | .ioctl = jfs_ioctl, | 1559 | .ioctl = jfs_ioctl, |
1566 | }; | 1560 | }; |
1567 | 1561 | ||
1568 | static int jfs_ci_hash(struct dentry *dir, struct qstr *this) | 1562 | static int jfs_ci_hash(struct dentry *dir, struct qstr *this) |
1569 | { | 1563 | { |
1570 | unsigned long hash; | 1564 | unsigned long hash; |
1571 | int i; | 1565 | int i; |
1572 | 1566 | ||
1573 | hash = init_name_hash(); | 1567 | hash = init_name_hash(); |
1574 | for (i=0; i < this->len; i++) | 1568 | for (i=0; i < this->len; i++) |
1575 | hash = partial_name_hash(tolower(this->name[i]), hash); | 1569 | hash = partial_name_hash(tolower(this->name[i]), hash); |
1576 | this->hash = end_name_hash(hash); | 1570 | this->hash = end_name_hash(hash); |
1577 | 1571 | ||
1578 | return 0; | 1572 | return 0; |
1579 | } | 1573 | } |
1580 | 1574 | ||
1581 | static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) | 1575 | static int jfs_ci_compare(struct dentry *dir, struct qstr *a, struct qstr *b) |
1582 | { | 1576 | { |
1583 | int i, result = 1; | 1577 | int i, result = 1; |
1584 | 1578 | ||
1585 | if (a->len != b->len) | 1579 | if (a->len != b->len) |
1586 | goto out; | 1580 | goto out; |
1587 | for (i=0; i < a->len; i++) { | 1581 | for (i=0; i < a->len; i++) { |
1588 | if (tolower(a->name[i]) != tolower(b->name[i])) | 1582 | if (tolower(a->name[i]) != tolower(b->name[i])) |
1589 | goto out; | 1583 | goto out; |
1590 | } | 1584 | } |
1591 | result = 0; | 1585 | result = 0; |
1592 | 1586 | ||
1593 | /* | 1587 | /* |
1594 | * We want creates to preserve case. A negative dentry, a, that | 1588 | * We want creates to preserve case. A negative dentry, a, that |
1595 | * has a different case than b may cause a new entry to be created | 1589 | * has a different case than b may cause a new entry to be created |
1596 | * with the wrong case. Since we can't tell if a comes from a negative | 1590 | * with the wrong case. Since we can't tell if a comes from a negative |
1597 | * dentry, we blindly replace it with b. This should be harmless if | 1591 | * dentry, we blindly replace it with b. This should be harmless if |
1598 | * a is not a negative dentry. | 1592 | * a is not a negative dentry. |
1599 | */ | 1593 | */ |
1600 | memcpy((unsigned char *)a->name, b->name, a->len); | 1594 | memcpy((unsigned char *)a->name, b->name, a->len); |
1601 | out: | 1595 | out: |
1602 | return result; | 1596 | return result; |
1603 | } | 1597 | } |
1604 | 1598 | ||
1605 | struct dentry_operations jfs_ci_dentry_operations = | 1599 | struct dentry_operations jfs_ci_dentry_operations = |
1606 | { | 1600 | { |
fs/jfs/super.c
1 | /* | 1 | /* |
2 | * Copyright (C) International Business Machines Corp., 2000-2004 | 2 | * Copyright (C) International Business Machines Corp., 2000-2004 |
3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 | 3 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or | 7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. | 8 | * (at your option) any later version. |
9 | * | 9 | * |
10 | * This program is distributed in the hope that it will be useful, | 10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
13 | * the GNU General Public License for more details. | 13 | * the GNU General Public License for more details. |
14 | * | 14 | * |
15 | * You should have received a copy of the GNU General Public License | 15 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/parser.h> | 22 | #include <linux/parser.h> |
23 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
24 | #include <linux/vfs.h> | 24 | #include <linux/vfs.h> |
25 | #include <linux/mount.h> | 25 | #include <linux/mount.h> |
26 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
28 | #include <linux/posix_acl.h> | 28 | #include <linux/posix_acl.h> |
29 | #include <linux/buffer_head.h> | 29 | #include <linux/buffer_head.h> |
30 | #include <linux/exportfs.h> | 30 | #include <linux/exportfs.h> |
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
33 | 33 | ||
34 | #include "jfs_incore.h" | 34 | #include "jfs_incore.h" |
35 | #include "jfs_filsys.h" | 35 | #include "jfs_filsys.h" |
36 | #include "jfs_inode.h" | 36 | #include "jfs_inode.h" |
37 | #include "jfs_metapage.h" | 37 | #include "jfs_metapage.h" |
38 | #include "jfs_superblock.h" | 38 | #include "jfs_superblock.h" |
39 | #include "jfs_dmap.h" | 39 | #include "jfs_dmap.h" |
40 | #include "jfs_imap.h" | 40 | #include "jfs_imap.h" |
41 | #include "jfs_acl.h" | 41 | #include "jfs_acl.h" |
42 | #include "jfs_debug.h" | 42 | #include "jfs_debug.h" |
43 | 43 | ||
44 | MODULE_DESCRIPTION("The Journaled Filesystem (JFS)"); | 44 | MODULE_DESCRIPTION("The Journaled Filesystem (JFS)"); |
45 | MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM"); | 45 | MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM"); |
46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
47 | 47 | ||
48 | static struct kmem_cache * jfs_inode_cachep; | 48 | static struct kmem_cache * jfs_inode_cachep; |
49 | 49 | ||
50 | static const struct super_operations jfs_super_operations; | 50 | static const struct super_operations jfs_super_operations; |
51 | static const struct export_operations jfs_export_operations; | 51 | static const struct export_operations jfs_export_operations; |
52 | static struct file_system_type jfs_fs_type; | 52 | static struct file_system_type jfs_fs_type; |
53 | 53 | ||
54 | #define MAX_COMMIT_THREADS 64 | 54 | #define MAX_COMMIT_THREADS 64 |
55 | static int commit_threads = 0; | 55 | static int commit_threads = 0; |
56 | module_param(commit_threads, int, 0); | 56 | module_param(commit_threads, int, 0); |
57 | MODULE_PARM_DESC(commit_threads, "Number of commit threads"); | 57 | MODULE_PARM_DESC(commit_threads, "Number of commit threads"); |
58 | 58 | ||
59 | static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS]; | 59 | static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS]; |
60 | struct task_struct *jfsIOthread; | 60 | struct task_struct *jfsIOthread; |
61 | struct task_struct *jfsSyncThread; | 61 | struct task_struct *jfsSyncThread; |
62 | 62 | ||
63 | #ifdef CONFIG_JFS_DEBUG | 63 | #ifdef CONFIG_JFS_DEBUG |
64 | int jfsloglevel = JFS_LOGLEVEL_WARN; | 64 | int jfsloglevel = JFS_LOGLEVEL_WARN; |
65 | module_param(jfsloglevel, int, 0644); | 65 | module_param(jfsloglevel, int, 0644); |
66 | MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); | 66 | MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)"); |
67 | #endif | 67 | #endif |
68 | 68 | ||
69 | static void jfs_handle_error(struct super_block *sb) | 69 | static void jfs_handle_error(struct super_block *sb) |
70 | { | 70 | { |
71 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 71 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
72 | 72 | ||
73 | if (sb->s_flags & MS_RDONLY) | 73 | if (sb->s_flags & MS_RDONLY) |
74 | return; | 74 | return; |
75 | 75 | ||
76 | updateSuper(sb, FM_DIRTY); | 76 | updateSuper(sb, FM_DIRTY); |
77 | 77 | ||
78 | if (sbi->flag & JFS_ERR_PANIC) | 78 | if (sbi->flag & JFS_ERR_PANIC) |
79 | panic("JFS (device %s): panic forced after error\n", | 79 | panic("JFS (device %s): panic forced after error\n", |
80 | sb->s_id); | 80 | sb->s_id); |
81 | else if (sbi->flag & JFS_ERR_REMOUNT_RO) { | 81 | else if (sbi->flag & JFS_ERR_REMOUNT_RO) { |
82 | jfs_err("ERROR: (device %s): remounting filesystem " | 82 | jfs_err("ERROR: (device %s): remounting filesystem " |
83 | "as read-only\n", | 83 | "as read-only\n", |
84 | sb->s_id); | 84 | sb->s_id); |
85 | sb->s_flags |= MS_RDONLY; | 85 | sb->s_flags |= MS_RDONLY; |
86 | } | 86 | } |
87 | 87 | ||
88 | /* nothing is done for continue beyond marking the superblock dirty */ | 88 | /* nothing is done for continue beyond marking the superblock dirty */ |
89 | } | 89 | } |
90 | 90 | ||
91 | void jfs_error(struct super_block *sb, const char * function, ...) | 91 | void jfs_error(struct super_block *sb, const char * function, ...) |
92 | { | 92 | { |
93 | static char error_buf[256]; | 93 | static char error_buf[256]; |
94 | va_list args; | 94 | va_list args; |
95 | 95 | ||
96 | va_start(args, function); | 96 | va_start(args, function); |
97 | vsnprintf(error_buf, sizeof(error_buf), function, args); | 97 | vsnprintf(error_buf, sizeof(error_buf), function, args); |
98 | va_end(args); | 98 | va_end(args); |
99 | 99 | ||
100 | printk(KERN_ERR "ERROR: (device %s): %s\n", sb->s_id, error_buf); | 100 | printk(KERN_ERR "ERROR: (device %s): %s\n", sb->s_id, error_buf); |
101 | 101 | ||
102 | jfs_handle_error(sb); | 102 | jfs_handle_error(sb); |
103 | } | 103 | } |
104 | 104 | ||
105 | static struct inode *jfs_alloc_inode(struct super_block *sb) | 105 | static struct inode *jfs_alloc_inode(struct super_block *sb) |
106 | { | 106 | { |
107 | struct jfs_inode_info *jfs_inode; | 107 | struct jfs_inode_info *jfs_inode; |
108 | 108 | ||
109 | jfs_inode = kmem_cache_alloc(jfs_inode_cachep, GFP_NOFS); | 109 | jfs_inode = kmem_cache_alloc(jfs_inode_cachep, GFP_NOFS); |
110 | if (!jfs_inode) | 110 | if (!jfs_inode) |
111 | return NULL; | 111 | return NULL; |
112 | return &jfs_inode->vfs_inode; | 112 | return &jfs_inode->vfs_inode; |
113 | } | 113 | } |
114 | 114 | ||
115 | static void jfs_destroy_inode(struct inode *inode) | 115 | static void jfs_destroy_inode(struct inode *inode) |
116 | { | 116 | { |
117 | struct jfs_inode_info *ji = JFS_IP(inode); | 117 | struct jfs_inode_info *ji = JFS_IP(inode); |
118 | 118 | ||
119 | BUG_ON(!list_empty(&ji->anon_inode_list)); | 119 | BUG_ON(!list_empty(&ji->anon_inode_list)); |
120 | 120 | ||
121 | spin_lock_irq(&ji->ag_lock); | 121 | spin_lock_irq(&ji->ag_lock); |
122 | if (ji->active_ag != -1) { | 122 | if (ji->active_ag != -1) { |
123 | struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; | 123 | struct bmap *bmap = JFS_SBI(inode->i_sb)->bmap; |
124 | atomic_dec(&bmap->db_active[ji->active_ag]); | 124 | atomic_dec(&bmap->db_active[ji->active_ag]); |
125 | ji->active_ag = -1; | 125 | ji->active_ag = -1; |
126 | } | 126 | } |
127 | spin_unlock_irq(&ji->ag_lock); | 127 | spin_unlock_irq(&ji->ag_lock); |
128 | 128 | ||
129 | #ifdef CONFIG_JFS_POSIX_ACL | 129 | #ifdef CONFIG_JFS_POSIX_ACL |
130 | if (ji->i_acl != JFS_ACL_NOT_CACHED) { | 130 | if (ji->i_acl != JFS_ACL_NOT_CACHED) { |
131 | posix_acl_release(ji->i_acl); | 131 | posix_acl_release(ji->i_acl); |
132 | ji->i_acl = JFS_ACL_NOT_CACHED; | 132 | ji->i_acl = JFS_ACL_NOT_CACHED; |
133 | } | 133 | } |
134 | if (ji->i_default_acl != JFS_ACL_NOT_CACHED) { | 134 | if (ji->i_default_acl != JFS_ACL_NOT_CACHED) { |
135 | posix_acl_release(ji->i_default_acl); | 135 | posix_acl_release(ji->i_default_acl); |
136 | ji->i_default_acl = JFS_ACL_NOT_CACHED; | 136 | ji->i_default_acl = JFS_ACL_NOT_CACHED; |
137 | } | 137 | } |
138 | #endif | 138 | #endif |
139 | 139 | ||
140 | kmem_cache_free(jfs_inode_cachep, ji); | 140 | kmem_cache_free(jfs_inode_cachep, ji); |
141 | } | 141 | } |
142 | 142 | ||
143 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 143 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
144 | { | 144 | { |
145 | struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb); | 145 | struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb); |
146 | s64 maxinodes; | 146 | s64 maxinodes; |
147 | struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; | 147 | struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; |
148 | 148 | ||
149 | jfs_info("In jfs_statfs"); | 149 | jfs_info("In jfs_statfs"); |
150 | buf->f_type = JFS_SUPER_MAGIC; | 150 | buf->f_type = JFS_SUPER_MAGIC; |
151 | buf->f_bsize = sbi->bsize; | 151 | buf->f_bsize = sbi->bsize; |
152 | buf->f_blocks = sbi->bmap->db_mapsize; | 152 | buf->f_blocks = sbi->bmap->db_mapsize; |
153 | buf->f_bfree = sbi->bmap->db_nfree; | 153 | buf->f_bfree = sbi->bmap->db_nfree; |
154 | buf->f_bavail = sbi->bmap->db_nfree; | 154 | buf->f_bavail = sbi->bmap->db_nfree; |
155 | /* | 155 | /* |
156 | * If we really return the number of allocated & free inodes, some | 156 | * If we really return the number of allocated & free inodes, some |
157 | * applications will fail because they won't see enough free inodes. | 157 | * applications will fail because they won't see enough free inodes. |
158 | * We'll try to calculate some guess as to how may inodes we can | 158 | * We'll try to calculate some guess as to how may inodes we can |
159 | * really allocate | 159 | * really allocate |
160 | * | 160 | * |
161 | * buf->f_files = atomic_read(&imap->im_numinos); | 161 | * buf->f_files = atomic_read(&imap->im_numinos); |
162 | * buf->f_ffree = atomic_read(&imap->im_numfree); | 162 | * buf->f_ffree = atomic_read(&imap->im_numfree); |
163 | */ | 163 | */ |
164 | maxinodes = min((s64) atomic_read(&imap->im_numinos) + | 164 | maxinodes = min((s64) atomic_read(&imap->im_numinos) + |
165 | ((sbi->bmap->db_nfree >> imap->im_l2nbperiext) | 165 | ((sbi->bmap->db_nfree >> imap->im_l2nbperiext) |
166 | << L2INOSPEREXT), (s64) 0xffffffffLL); | 166 | << L2INOSPEREXT), (s64) 0xffffffffLL); |
167 | buf->f_files = maxinodes; | 167 | buf->f_files = maxinodes; |
168 | buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) - | 168 | buf->f_ffree = maxinodes - (atomic_read(&imap->im_numinos) - |
169 | atomic_read(&imap->im_numfree)); | 169 | atomic_read(&imap->im_numfree)); |
170 | 170 | ||
171 | buf->f_namelen = JFS_NAME_MAX; | 171 | buf->f_namelen = JFS_NAME_MAX; |
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
175 | static void jfs_put_super(struct super_block *sb) | 175 | static void jfs_put_super(struct super_block *sb) |
176 | { | 176 | { |
177 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 177 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
178 | int rc; | 178 | int rc; |
179 | 179 | ||
180 | jfs_info("In jfs_put_super"); | 180 | jfs_info("In jfs_put_super"); |
181 | rc = jfs_umount(sb); | 181 | rc = jfs_umount(sb); |
182 | if (rc) | 182 | if (rc) |
183 | jfs_err("jfs_umount failed with return code %d", rc); | 183 | jfs_err("jfs_umount failed with return code %d", rc); |
184 | if (sbi->nls_tab) | 184 | if (sbi->nls_tab) |
185 | unload_nls(sbi->nls_tab); | 185 | unload_nls(sbi->nls_tab); |
186 | sbi->nls_tab = NULL; | 186 | sbi->nls_tab = NULL; |
187 | 187 | ||
188 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); | 188 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); |
189 | iput(sbi->direct_inode); | 189 | iput(sbi->direct_inode); |
190 | sbi->direct_inode = NULL; | 190 | sbi->direct_inode = NULL; |
191 | 191 | ||
192 | kfree(sbi); | 192 | kfree(sbi); |
193 | } | 193 | } |
194 | 194 | ||
195 | enum { | 195 | enum { |
196 | Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, | 196 | Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, |
197 | Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota, | 197 | Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota, |
198 | Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask | 198 | Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask |
199 | }; | 199 | }; |
200 | 200 | ||
201 | static match_table_t tokens = { | 201 | static match_table_t tokens = { |
202 | {Opt_integrity, "integrity"}, | 202 | {Opt_integrity, "integrity"}, |
203 | {Opt_nointegrity, "nointegrity"}, | 203 | {Opt_nointegrity, "nointegrity"}, |
204 | {Opt_iocharset, "iocharset=%s"}, | 204 | {Opt_iocharset, "iocharset=%s"}, |
205 | {Opt_resize, "resize=%u"}, | 205 | {Opt_resize, "resize=%u"}, |
206 | {Opt_resize_nosize, "resize"}, | 206 | {Opt_resize_nosize, "resize"}, |
207 | {Opt_errors, "errors=%s"}, | 207 | {Opt_errors, "errors=%s"}, |
208 | {Opt_ignore, "noquota"}, | 208 | {Opt_ignore, "noquota"}, |
209 | {Opt_ignore, "quota"}, | 209 | {Opt_ignore, "quota"}, |
210 | {Opt_usrquota, "usrquota"}, | 210 | {Opt_usrquota, "usrquota"}, |
211 | {Opt_grpquota, "grpquota"}, | 211 | {Opt_grpquota, "grpquota"}, |
212 | {Opt_uid, "uid=%u"}, | 212 | {Opt_uid, "uid=%u"}, |
213 | {Opt_gid, "gid=%u"}, | 213 | {Opt_gid, "gid=%u"}, |
214 | {Opt_umask, "umask=%u"}, | 214 | {Opt_umask, "umask=%u"}, |
215 | {Opt_err, NULL} | 215 | {Opt_err, NULL} |
216 | }; | 216 | }; |
217 | 217 | ||
218 | static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, | 218 | static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, |
219 | int *flag) | 219 | int *flag) |
220 | { | 220 | { |
221 | void *nls_map = (void *)-1; /* -1: no change; NULL: none */ | 221 | void *nls_map = (void *)-1; /* -1: no change; NULL: none */ |
222 | char *p; | 222 | char *p; |
223 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 223 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
224 | 224 | ||
225 | *newLVSize = 0; | 225 | *newLVSize = 0; |
226 | 226 | ||
227 | if (!options) | 227 | if (!options) |
228 | return 1; | 228 | return 1; |
229 | 229 | ||
230 | while ((p = strsep(&options, ",")) != NULL) { | 230 | while ((p = strsep(&options, ",")) != NULL) { |
231 | substring_t args[MAX_OPT_ARGS]; | 231 | substring_t args[MAX_OPT_ARGS]; |
232 | int token; | 232 | int token; |
233 | if (!*p) | 233 | if (!*p) |
234 | continue; | 234 | continue; |
235 | 235 | ||
236 | token = match_token(p, tokens, args); | 236 | token = match_token(p, tokens, args); |
237 | switch (token) { | 237 | switch (token) { |
238 | case Opt_integrity: | 238 | case Opt_integrity: |
239 | *flag &= ~JFS_NOINTEGRITY; | 239 | *flag &= ~JFS_NOINTEGRITY; |
240 | break; | 240 | break; |
241 | case Opt_nointegrity: | 241 | case Opt_nointegrity: |
242 | *flag |= JFS_NOINTEGRITY; | 242 | *flag |= JFS_NOINTEGRITY; |
243 | break; | 243 | break; |
244 | case Opt_ignore: | 244 | case Opt_ignore: |
245 | /* Silently ignore the quota options */ | 245 | /* Silently ignore the quota options */ |
246 | /* Don't do anything ;-) */ | 246 | /* Don't do anything ;-) */ |
247 | break; | 247 | break; |
248 | case Opt_iocharset: | 248 | case Opt_iocharset: |
249 | if (nls_map && nls_map != (void *) -1) | 249 | if (nls_map && nls_map != (void *) -1) |
250 | unload_nls(nls_map); | 250 | unload_nls(nls_map); |
251 | if (!strcmp(args[0].from, "none")) | 251 | if (!strcmp(args[0].from, "none")) |
252 | nls_map = NULL; | 252 | nls_map = NULL; |
253 | else { | 253 | else { |
254 | nls_map = load_nls(args[0].from); | 254 | nls_map = load_nls(args[0].from); |
255 | if (!nls_map) { | 255 | if (!nls_map) { |
256 | printk(KERN_ERR | 256 | printk(KERN_ERR |
257 | "JFS: charset not found\n"); | 257 | "JFS: charset not found\n"); |
258 | goto cleanup; | 258 | goto cleanup; |
259 | } | 259 | } |
260 | } | 260 | } |
261 | break; | 261 | break; |
262 | case Opt_resize: | 262 | case Opt_resize: |
263 | { | 263 | { |
264 | char *resize = args[0].from; | 264 | char *resize = args[0].from; |
265 | *newLVSize = simple_strtoull(resize, &resize, 0); | 265 | *newLVSize = simple_strtoull(resize, &resize, 0); |
266 | break; | 266 | break; |
267 | } | 267 | } |
268 | case Opt_resize_nosize: | 268 | case Opt_resize_nosize: |
269 | { | 269 | { |
270 | *newLVSize = sb->s_bdev->bd_inode->i_size >> | 270 | *newLVSize = sb->s_bdev->bd_inode->i_size >> |
271 | sb->s_blocksize_bits; | 271 | sb->s_blocksize_bits; |
272 | if (*newLVSize == 0) | 272 | if (*newLVSize == 0) |
273 | printk(KERN_ERR | 273 | printk(KERN_ERR |
274 | "JFS: Cannot determine volume size\n"); | 274 | "JFS: Cannot determine volume size\n"); |
275 | break; | 275 | break; |
276 | } | 276 | } |
277 | case Opt_errors: | 277 | case Opt_errors: |
278 | { | 278 | { |
279 | char *errors = args[0].from; | 279 | char *errors = args[0].from; |
280 | if (!errors || !*errors) | 280 | if (!errors || !*errors) |
281 | goto cleanup; | 281 | goto cleanup; |
282 | if (!strcmp(errors, "continue")) { | 282 | if (!strcmp(errors, "continue")) { |
283 | *flag &= ~JFS_ERR_REMOUNT_RO; | 283 | *flag &= ~JFS_ERR_REMOUNT_RO; |
284 | *flag &= ~JFS_ERR_PANIC; | 284 | *flag &= ~JFS_ERR_PANIC; |
285 | *flag |= JFS_ERR_CONTINUE; | 285 | *flag |= JFS_ERR_CONTINUE; |
286 | } else if (!strcmp(errors, "remount-ro")) { | 286 | } else if (!strcmp(errors, "remount-ro")) { |
287 | *flag &= ~JFS_ERR_CONTINUE; | 287 | *flag &= ~JFS_ERR_CONTINUE; |
288 | *flag &= ~JFS_ERR_PANIC; | 288 | *flag &= ~JFS_ERR_PANIC; |
289 | *flag |= JFS_ERR_REMOUNT_RO; | 289 | *flag |= JFS_ERR_REMOUNT_RO; |
290 | } else if (!strcmp(errors, "panic")) { | 290 | } else if (!strcmp(errors, "panic")) { |
291 | *flag &= ~JFS_ERR_CONTINUE; | 291 | *flag &= ~JFS_ERR_CONTINUE; |
292 | *flag &= ~JFS_ERR_REMOUNT_RO; | 292 | *flag &= ~JFS_ERR_REMOUNT_RO; |
293 | *flag |= JFS_ERR_PANIC; | 293 | *flag |= JFS_ERR_PANIC; |
294 | } else { | 294 | } else { |
295 | printk(KERN_ERR | 295 | printk(KERN_ERR |
296 | "JFS: %s is an invalid error handler\n", | 296 | "JFS: %s is an invalid error handler\n", |
297 | errors); | 297 | errors); |
298 | goto cleanup; | 298 | goto cleanup; |
299 | } | 299 | } |
300 | break; | 300 | break; |
301 | } | 301 | } |
302 | 302 | ||
303 | #ifdef CONFIG_QUOTA | 303 | #ifdef CONFIG_QUOTA |
304 | case Opt_quota: | 304 | case Opt_quota: |
305 | case Opt_usrquota: | 305 | case Opt_usrquota: |
306 | *flag |= JFS_USRQUOTA; | 306 | *flag |= JFS_USRQUOTA; |
307 | break; | 307 | break; |
308 | case Opt_grpquota: | 308 | case Opt_grpquota: |
309 | *flag |= JFS_GRPQUOTA; | 309 | *flag |= JFS_GRPQUOTA; |
310 | break; | 310 | break; |
311 | #else | 311 | #else |
312 | case Opt_usrquota: | 312 | case Opt_usrquota: |
313 | case Opt_grpquota: | 313 | case Opt_grpquota: |
314 | case Opt_quota: | 314 | case Opt_quota: |
315 | printk(KERN_ERR | 315 | printk(KERN_ERR |
316 | "JFS: quota operations not supported\n"); | 316 | "JFS: quota operations not supported\n"); |
317 | break; | 317 | break; |
318 | #endif | 318 | #endif |
319 | case Opt_uid: | 319 | case Opt_uid: |
320 | { | 320 | { |
321 | char *uid = args[0].from; | 321 | char *uid = args[0].from; |
322 | sbi->uid = simple_strtoul(uid, &uid, 0); | 322 | sbi->uid = simple_strtoul(uid, &uid, 0); |
323 | break; | 323 | break; |
324 | } | 324 | } |
325 | case Opt_gid: | 325 | case Opt_gid: |
326 | { | 326 | { |
327 | char *gid = args[0].from; | 327 | char *gid = args[0].from; |
328 | sbi->gid = simple_strtoul(gid, &gid, 0); | 328 | sbi->gid = simple_strtoul(gid, &gid, 0); |
329 | break; | 329 | break; |
330 | } | 330 | } |
331 | case Opt_umask: | 331 | case Opt_umask: |
332 | { | 332 | { |
333 | char *umask = args[0].from; | 333 | char *umask = args[0].from; |
334 | sbi->umask = simple_strtoul(umask, &umask, 8); | 334 | sbi->umask = simple_strtoul(umask, &umask, 8); |
335 | if (sbi->umask & ~0777) { | 335 | if (sbi->umask & ~0777) { |
336 | printk(KERN_ERR | 336 | printk(KERN_ERR |
337 | "JFS: Invalid value of umask\n"); | 337 | "JFS: Invalid value of umask\n"); |
338 | goto cleanup; | 338 | goto cleanup; |
339 | } | 339 | } |
340 | break; | 340 | break; |
341 | } | 341 | } |
342 | default: | 342 | default: |
343 | printk("jfs: Unrecognized mount option \"%s\" " | 343 | printk("jfs: Unrecognized mount option \"%s\" " |
344 | " or missing value\n", p); | 344 | " or missing value\n", p); |
345 | goto cleanup; | 345 | goto cleanup; |
346 | } | 346 | } |
347 | } | 347 | } |
348 | 348 | ||
349 | if (nls_map != (void *) -1) { | 349 | if (nls_map != (void *) -1) { |
350 | /* Discard old (if remount) */ | 350 | /* Discard old (if remount) */ |
351 | if (sbi->nls_tab) | 351 | if (sbi->nls_tab) |
352 | unload_nls(sbi->nls_tab); | 352 | unload_nls(sbi->nls_tab); |
353 | sbi->nls_tab = nls_map; | 353 | sbi->nls_tab = nls_map; |
354 | } | 354 | } |
355 | return 1; | 355 | return 1; |
356 | 356 | ||
357 | cleanup: | 357 | cleanup: |
358 | if (nls_map && nls_map != (void *) -1) | 358 | if (nls_map && nls_map != (void *) -1) |
359 | unload_nls(nls_map); | 359 | unload_nls(nls_map); |
360 | return 0; | 360 | return 0; |
361 | } | 361 | } |
362 | 362 | ||
363 | static int jfs_remount(struct super_block *sb, int *flags, char *data) | 363 | static int jfs_remount(struct super_block *sb, int *flags, char *data) |
364 | { | 364 | { |
365 | s64 newLVSize = 0; | 365 | s64 newLVSize = 0; |
366 | int rc = 0; | 366 | int rc = 0; |
367 | int flag = JFS_SBI(sb)->flag; | 367 | int flag = JFS_SBI(sb)->flag; |
368 | 368 | ||
369 | if (!parse_options(data, sb, &newLVSize, &flag)) { | 369 | if (!parse_options(data, sb, &newLVSize, &flag)) { |
370 | return -EINVAL; | 370 | return -EINVAL; |
371 | } | 371 | } |
372 | if (newLVSize) { | 372 | if (newLVSize) { |
373 | if (sb->s_flags & MS_RDONLY) { | 373 | if (sb->s_flags & MS_RDONLY) { |
374 | printk(KERN_ERR | 374 | printk(KERN_ERR |
375 | "JFS: resize requires volume to be mounted read-write\n"); | 375 | "JFS: resize requires volume to be mounted read-write\n"); |
376 | return -EROFS; | 376 | return -EROFS; |
377 | } | 377 | } |
378 | rc = jfs_extendfs(sb, newLVSize, 0); | 378 | rc = jfs_extendfs(sb, newLVSize, 0); |
379 | if (rc) | 379 | if (rc) |
380 | return rc; | 380 | return rc; |
381 | } | 381 | } |
382 | 382 | ||
383 | if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { | 383 | if ((sb->s_flags & MS_RDONLY) && !(*flags & MS_RDONLY)) { |
384 | /* | 384 | /* |
385 | * Invalidate any previously read metadata. fsck may have | 385 | * Invalidate any previously read metadata. fsck may have |
386 | * changed the on-disk data since we mounted r/o | 386 | * changed the on-disk data since we mounted r/o |
387 | */ | 387 | */ |
388 | truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0); | 388 | truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0); |
389 | 389 | ||
390 | JFS_SBI(sb)->flag = flag; | 390 | JFS_SBI(sb)->flag = flag; |
391 | return jfs_mount_rw(sb, 1); | 391 | return jfs_mount_rw(sb, 1); |
392 | } | 392 | } |
393 | if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) { | 393 | if ((!(sb->s_flags & MS_RDONLY)) && (*flags & MS_RDONLY)) { |
394 | rc = jfs_umount_rw(sb); | 394 | rc = jfs_umount_rw(sb); |
395 | JFS_SBI(sb)->flag = flag; | 395 | JFS_SBI(sb)->flag = flag; |
396 | return rc; | 396 | return rc; |
397 | } | 397 | } |
398 | if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) | 398 | if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) |
399 | if (!(sb->s_flags & MS_RDONLY)) { | 399 | if (!(sb->s_flags & MS_RDONLY)) { |
400 | rc = jfs_umount_rw(sb); | 400 | rc = jfs_umount_rw(sb); |
401 | if (rc) | 401 | if (rc) |
402 | return rc; | 402 | return rc; |
403 | JFS_SBI(sb)->flag = flag; | 403 | JFS_SBI(sb)->flag = flag; |
404 | return jfs_mount_rw(sb, 1); | 404 | return jfs_mount_rw(sb, 1); |
405 | } | 405 | } |
406 | JFS_SBI(sb)->flag = flag; | 406 | JFS_SBI(sb)->flag = flag; |
407 | 407 | ||
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | static int jfs_fill_super(struct super_block *sb, void *data, int silent) | 411 | static int jfs_fill_super(struct super_block *sb, void *data, int silent) |
412 | { | 412 | { |
413 | struct jfs_sb_info *sbi; | 413 | struct jfs_sb_info *sbi; |
414 | struct inode *inode; | 414 | struct inode *inode; |
415 | int rc; | 415 | int rc; |
416 | s64 newLVSize = 0; | 416 | s64 newLVSize = 0; |
417 | int flag; | 417 | int flag, ret = -EINVAL; |
418 | 418 | ||
419 | jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags); | 419 | jfs_info("In jfs_read_super: s_flags=0x%lx", sb->s_flags); |
420 | 420 | ||
421 | if (!new_valid_dev(sb->s_bdev->bd_dev)) | 421 | if (!new_valid_dev(sb->s_bdev->bd_dev)) |
422 | return -EOVERFLOW; | 422 | return -EOVERFLOW; |
423 | 423 | ||
424 | sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL); | 424 | sbi = kzalloc(sizeof (struct jfs_sb_info), GFP_KERNEL); |
425 | if (!sbi) | 425 | if (!sbi) |
426 | return -ENOMEM; | 426 | return -ENOMEM; |
427 | sb->s_fs_info = sbi; | 427 | sb->s_fs_info = sbi; |
428 | sbi->sb = sb; | 428 | sbi->sb = sb; |
429 | sbi->uid = sbi->gid = sbi->umask = -1; | 429 | sbi->uid = sbi->gid = sbi->umask = -1; |
430 | 430 | ||
431 | /* initialize the mount flag and determine the default error handler */ | 431 | /* initialize the mount flag and determine the default error handler */ |
432 | flag = JFS_ERR_REMOUNT_RO; | 432 | flag = JFS_ERR_REMOUNT_RO; |
433 | 433 | ||
434 | if (!parse_options((char *) data, sb, &newLVSize, &flag)) { | 434 | if (!parse_options((char *) data, sb, &newLVSize, &flag)) { |
435 | kfree(sbi); | 435 | kfree(sbi); |
436 | return -EINVAL; | 436 | return -EINVAL; |
437 | } | 437 | } |
438 | sbi->flag = flag; | 438 | sbi->flag = flag; |
439 | 439 | ||
440 | #ifdef CONFIG_JFS_POSIX_ACL | 440 | #ifdef CONFIG_JFS_POSIX_ACL |
441 | sb->s_flags |= MS_POSIXACL; | 441 | sb->s_flags |= MS_POSIXACL; |
442 | #endif | 442 | #endif |
443 | 443 | ||
444 | if (newLVSize) { | 444 | if (newLVSize) { |
445 | printk(KERN_ERR "resize option for remount only\n"); | 445 | printk(KERN_ERR "resize option for remount only\n"); |
446 | return -EINVAL; | 446 | return -EINVAL; |
447 | } | 447 | } |
448 | 448 | ||
449 | /* | 449 | /* |
450 | * Initialize blocksize to 4K. | 450 | * Initialize blocksize to 4K. |
451 | */ | 451 | */ |
452 | sb_set_blocksize(sb, PSIZE); | 452 | sb_set_blocksize(sb, PSIZE); |
453 | 453 | ||
454 | /* | 454 | /* |
455 | * Set method vectors. | 455 | * Set method vectors. |
456 | */ | 456 | */ |
457 | sb->s_op = &jfs_super_operations; | 457 | sb->s_op = &jfs_super_operations; |
458 | sb->s_export_op = &jfs_export_operations; | 458 | sb->s_export_op = &jfs_export_operations; |
459 | 459 | ||
460 | /* | 460 | /* |
461 | * Initialize direct-mapping inode/address-space | 461 | * Initialize direct-mapping inode/address-space |
462 | */ | 462 | */ |
463 | inode = new_inode(sb); | 463 | inode = new_inode(sb); |
464 | if (inode == NULL) | 464 | if (inode == NULL) { |
465 | ret = -ENOMEM; | ||
465 | goto out_kfree; | 466 | goto out_kfree; |
467 | } | ||
466 | inode->i_ino = 0; | 468 | inode->i_ino = 0; |
467 | inode->i_nlink = 1; | 469 | inode->i_nlink = 1; |
468 | inode->i_size = sb->s_bdev->bd_inode->i_size; | 470 | inode->i_size = sb->s_bdev->bd_inode->i_size; |
469 | inode->i_mapping->a_ops = &jfs_metapage_aops; | 471 | inode->i_mapping->a_ops = &jfs_metapage_aops; |
470 | insert_inode_hash(inode); | 472 | insert_inode_hash(inode); |
471 | mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); | 473 | mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); |
472 | 474 | ||
473 | sbi->direct_inode = inode; | 475 | sbi->direct_inode = inode; |
474 | 476 | ||
475 | rc = jfs_mount(sb); | 477 | rc = jfs_mount(sb); |
476 | if (rc) { | 478 | if (rc) { |
477 | if (!silent) { | 479 | if (!silent) { |
478 | jfs_err("jfs_mount failed w/return code = %d", rc); | 480 | jfs_err("jfs_mount failed w/return code = %d", rc); |
479 | } | 481 | } |
480 | goto out_mount_failed; | 482 | goto out_mount_failed; |
481 | } | 483 | } |
482 | if (sb->s_flags & MS_RDONLY) | 484 | if (sb->s_flags & MS_RDONLY) |
483 | sbi->log = NULL; | 485 | sbi->log = NULL; |
484 | else { | 486 | else { |
485 | rc = jfs_mount_rw(sb, 0); | 487 | rc = jfs_mount_rw(sb, 0); |
486 | if (rc) { | 488 | if (rc) { |
487 | if (!silent) { | 489 | if (!silent) { |
488 | jfs_err("jfs_mount_rw failed, return code = %d", | 490 | jfs_err("jfs_mount_rw failed, return code = %d", |
489 | rc); | 491 | rc); |
490 | } | 492 | } |
491 | goto out_no_rw; | 493 | goto out_no_rw; |
492 | } | 494 | } |
493 | } | 495 | } |
494 | 496 | ||
495 | sb->s_magic = JFS_SUPER_MAGIC; | 497 | sb->s_magic = JFS_SUPER_MAGIC; |
496 | 498 | ||
497 | inode = iget(sb, ROOT_I); | 499 | inode = jfs_iget(sb, ROOT_I); |
498 | if (!inode || is_bad_inode(inode)) | 500 | if (IS_ERR(inode)) { |
501 | ret = PTR_ERR(inode); | ||
499 | goto out_no_root; | 502 | goto out_no_root; |
503 | } | ||
500 | sb->s_root = d_alloc_root(inode); | 504 | sb->s_root = d_alloc_root(inode); |
501 | if (!sb->s_root) | 505 | if (!sb->s_root) |
502 | goto out_no_root; | 506 | goto out_no_root; |
503 | 507 | ||
504 | if (sbi->mntflag & JFS_OS2) | 508 | if (sbi->mntflag & JFS_OS2) |
505 | sb->s_root->d_op = &jfs_ci_dentry_operations; | 509 | sb->s_root->d_op = &jfs_ci_dentry_operations; |
506 | 510 | ||
507 | /* logical blocks are represented by 40 bits in pxd_t, etc. */ | 511 | /* logical blocks are represented by 40 bits in pxd_t, etc. */ |
508 | sb->s_maxbytes = ((u64) sb->s_blocksize) << 40; | 512 | sb->s_maxbytes = ((u64) sb->s_blocksize) << 40; |
509 | #if BITS_PER_LONG == 32 | 513 | #if BITS_PER_LONG == 32 |
510 | /* | 514 | /* |
511 | * Page cache is indexed by long. | 515 | * Page cache is indexed by long. |
512 | * I would use MAX_LFS_FILESIZE, but it's only half as big | 516 | * I would use MAX_LFS_FILESIZE, but it's only half as big |
513 | */ | 517 | */ |
514 | sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes); | 518 | sb->s_maxbytes = min(((u64) PAGE_CACHE_SIZE << 32) - 1, sb->s_maxbytes); |
515 | #endif | 519 | #endif |
516 | sb->s_time_gran = 1; | 520 | sb->s_time_gran = 1; |
517 | return 0; | 521 | return 0; |
518 | 522 | ||
519 | out_no_root: | 523 | out_no_root: |
520 | jfs_err("jfs_read_super: get root inode failed"); | 524 | jfs_err("jfs_read_super: get root inode failed"); |
521 | if (inode) | 525 | if (inode) |
522 | iput(inode); | 526 | iput(inode); |
523 | 527 | ||
524 | out_no_rw: | 528 | out_no_rw: |
525 | rc = jfs_umount(sb); | 529 | rc = jfs_umount(sb); |
526 | if (rc) { | 530 | if (rc) { |
527 | jfs_err("jfs_umount failed with return code %d", rc); | 531 | jfs_err("jfs_umount failed with return code %d", rc); |
528 | } | 532 | } |
529 | out_mount_failed: | 533 | out_mount_failed: |
530 | filemap_write_and_wait(sbi->direct_inode->i_mapping); | 534 | filemap_write_and_wait(sbi->direct_inode->i_mapping); |
531 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); | 535 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); |
532 | make_bad_inode(sbi->direct_inode); | 536 | make_bad_inode(sbi->direct_inode); |
533 | iput(sbi->direct_inode); | 537 | iput(sbi->direct_inode); |
534 | sbi->direct_inode = NULL; | 538 | sbi->direct_inode = NULL; |
535 | out_kfree: | 539 | out_kfree: |
536 | if (sbi->nls_tab) | 540 | if (sbi->nls_tab) |
537 | unload_nls(sbi->nls_tab); | 541 | unload_nls(sbi->nls_tab); |
538 | kfree(sbi); | 542 | kfree(sbi); |
539 | return -EINVAL; | 543 | return ret; |
540 | } | 544 | } |
541 | 545 | ||
542 | static void jfs_write_super_lockfs(struct super_block *sb) | 546 | static void jfs_write_super_lockfs(struct super_block *sb) |
543 | { | 547 | { |
544 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 548 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
545 | struct jfs_log *log = sbi->log; | 549 | struct jfs_log *log = sbi->log; |
546 | 550 | ||
547 | if (!(sb->s_flags & MS_RDONLY)) { | 551 | if (!(sb->s_flags & MS_RDONLY)) { |
548 | txQuiesce(sb); | 552 | txQuiesce(sb); |
549 | lmLogShutdown(log); | 553 | lmLogShutdown(log); |
550 | updateSuper(sb, FM_CLEAN); | 554 | updateSuper(sb, FM_CLEAN); |
551 | } | 555 | } |
552 | } | 556 | } |
553 | 557 | ||
554 | static void jfs_unlockfs(struct super_block *sb) | 558 | static void jfs_unlockfs(struct super_block *sb) |
555 | { | 559 | { |
556 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 560 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
557 | struct jfs_log *log = sbi->log; | 561 | struct jfs_log *log = sbi->log; |
558 | int rc = 0; | 562 | int rc = 0; |
559 | 563 | ||
560 | if (!(sb->s_flags & MS_RDONLY)) { | 564 | if (!(sb->s_flags & MS_RDONLY)) { |
561 | updateSuper(sb, FM_MOUNT); | 565 | updateSuper(sb, FM_MOUNT); |
562 | if ((rc = lmLogInit(log))) | 566 | if ((rc = lmLogInit(log))) |
563 | jfs_err("jfs_unlock failed with return code %d", rc); | 567 | jfs_err("jfs_unlock failed with return code %d", rc); |
564 | else | 568 | else |
565 | txResume(sb); | 569 | txResume(sb); |
566 | } | 570 | } |
567 | } | 571 | } |
568 | 572 | ||
569 | static int jfs_get_sb(struct file_system_type *fs_type, | 573 | static int jfs_get_sb(struct file_system_type *fs_type, |
570 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 574 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
571 | { | 575 | { |
572 | return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super, | 576 | return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super, |
573 | mnt); | 577 | mnt); |
574 | } | 578 | } |
575 | 579 | ||
576 | static int jfs_sync_fs(struct super_block *sb, int wait) | 580 | static int jfs_sync_fs(struct super_block *sb, int wait) |
577 | { | 581 | { |
578 | struct jfs_log *log = JFS_SBI(sb)->log; | 582 | struct jfs_log *log = JFS_SBI(sb)->log; |
579 | 583 | ||
580 | /* log == NULL indicates read-only mount */ | 584 | /* log == NULL indicates read-only mount */ |
581 | if (log) { | 585 | if (log) { |
582 | jfs_flush_journal(log, wait); | 586 | jfs_flush_journal(log, wait); |
583 | jfs_syncpt(log, 0); | 587 | jfs_syncpt(log, 0); |
584 | } | 588 | } |
585 | 589 | ||
586 | return 0; | 590 | return 0; |
587 | } | 591 | } |
588 | 592 | ||
589 | static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | 593 | static int jfs_show_options(struct seq_file *seq, struct vfsmount *vfs) |
590 | { | 594 | { |
591 | struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb); | 595 | struct jfs_sb_info *sbi = JFS_SBI(vfs->mnt_sb); |
592 | 596 | ||
593 | if (sbi->uid != -1) | 597 | if (sbi->uid != -1) |
594 | seq_printf(seq, ",uid=%d", sbi->uid); | 598 | seq_printf(seq, ",uid=%d", sbi->uid); |
595 | if (sbi->gid != -1) | 599 | if (sbi->gid != -1) |
596 | seq_printf(seq, ",gid=%d", sbi->gid); | 600 | seq_printf(seq, ",gid=%d", sbi->gid); |
597 | if (sbi->umask != -1) | 601 | if (sbi->umask != -1) |
598 | seq_printf(seq, ",umask=%03o", sbi->umask); | 602 | seq_printf(seq, ",umask=%03o", sbi->umask); |
599 | if (sbi->flag & JFS_NOINTEGRITY) | 603 | if (sbi->flag & JFS_NOINTEGRITY) |
600 | seq_puts(seq, ",nointegrity"); | 604 | seq_puts(seq, ",nointegrity"); |
601 | if (sbi->nls_tab) | 605 | if (sbi->nls_tab) |
602 | seq_printf(seq, ",iocharset=%s", sbi->nls_tab->charset); | 606 | seq_printf(seq, ",iocharset=%s", sbi->nls_tab->charset); |
603 | if (sbi->flag & JFS_ERR_CONTINUE) | 607 | if (sbi->flag & JFS_ERR_CONTINUE) |
604 | seq_printf(seq, ",errors=continue"); | 608 | seq_printf(seq, ",errors=continue"); |
605 | if (sbi->flag & JFS_ERR_PANIC) | 609 | if (sbi->flag & JFS_ERR_PANIC) |
606 | seq_printf(seq, ",errors=panic"); | 610 | seq_printf(seq, ",errors=panic"); |
607 | 611 | ||
608 | #ifdef CONFIG_QUOTA | 612 | #ifdef CONFIG_QUOTA |
609 | if (sbi->flag & JFS_USRQUOTA) | 613 | if (sbi->flag & JFS_USRQUOTA) |
610 | seq_puts(seq, ",usrquota"); | 614 | seq_puts(seq, ",usrquota"); |
611 | 615 | ||
612 | if (sbi->flag & JFS_GRPQUOTA) | 616 | if (sbi->flag & JFS_GRPQUOTA) |
613 | seq_puts(seq, ",grpquota"); | 617 | seq_puts(seq, ",grpquota"); |
614 | #endif | 618 | #endif |
615 | 619 | ||
616 | return 0; | 620 | return 0; |
617 | } | 621 | } |
618 | 622 | ||
619 | #ifdef CONFIG_QUOTA | 623 | #ifdef CONFIG_QUOTA |
620 | 624 | ||
621 | /* Read data from quotafile - avoid pagecache and such because we cannot afford | 625 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
622 | * acquiring the locks... As quota files are never truncated and quota code | 626 | * acquiring the locks... As quota files are never truncated and quota code |
623 | * itself serializes the operations (and noone else should touch the files) | 627 | * itself serializes the operations (and noone else should touch the files) |
624 | * we don't have to be afraid of races */ | 628 | * we don't have to be afraid of races */ |
625 | static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, | 629 | static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, |
626 | size_t len, loff_t off) | 630 | size_t len, loff_t off) |
627 | { | 631 | { |
628 | struct inode *inode = sb_dqopt(sb)->files[type]; | 632 | struct inode *inode = sb_dqopt(sb)->files[type]; |
629 | sector_t blk = off >> sb->s_blocksize_bits; | 633 | sector_t blk = off >> sb->s_blocksize_bits; |
630 | int err = 0; | 634 | int err = 0; |
631 | int offset = off & (sb->s_blocksize - 1); | 635 | int offset = off & (sb->s_blocksize - 1); |
632 | int tocopy; | 636 | int tocopy; |
633 | size_t toread; | 637 | size_t toread; |
634 | struct buffer_head tmp_bh; | 638 | struct buffer_head tmp_bh; |
635 | struct buffer_head *bh; | 639 | struct buffer_head *bh; |
636 | loff_t i_size = i_size_read(inode); | 640 | loff_t i_size = i_size_read(inode); |
637 | 641 | ||
638 | if (off > i_size) | 642 | if (off > i_size) |
639 | return 0; | 643 | return 0; |
640 | if (off+len > i_size) | 644 | if (off+len > i_size) |
641 | len = i_size-off; | 645 | len = i_size-off; |
642 | toread = len; | 646 | toread = len; |
643 | while (toread > 0) { | 647 | while (toread > 0) { |
644 | tocopy = sb->s_blocksize - offset < toread ? | 648 | tocopy = sb->s_blocksize - offset < toread ? |
645 | sb->s_blocksize - offset : toread; | 649 | sb->s_blocksize - offset : toread; |
646 | 650 | ||
647 | tmp_bh.b_state = 0; | 651 | tmp_bh.b_state = 0; |
648 | tmp_bh.b_size = 1 << inode->i_blkbits; | 652 | tmp_bh.b_size = 1 << inode->i_blkbits; |
649 | err = jfs_get_block(inode, blk, &tmp_bh, 0); | 653 | err = jfs_get_block(inode, blk, &tmp_bh, 0); |
650 | if (err) | 654 | if (err) |
651 | return err; | 655 | return err; |
652 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ | 656 | if (!buffer_mapped(&tmp_bh)) /* A hole? */ |
653 | memset(data, 0, tocopy); | 657 | memset(data, 0, tocopy); |
654 | else { | 658 | else { |
655 | bh = sb_bread(sb, tmp_bh.b_blocknr); | 659 | bh = sb_bread(sb, tmp_bh.b_blocknr); |
656 | if (!bh) | 660 | if (!bh) |
657 | return -EIO; | 661 | return -EIO; |
658 | memcpy(data, bh->b_data+offset, tocopy); | 662 | memcpy(data, bh->b_data+offset, tocopy); |
659 | brelse(bh); | 663 | brelse(bh); |
660 | } | 664 | } |
661 | offset = 0; | 665 | offset = 0; |
662 | toread -= tocopy; | 666 | toread -= tocopy; |
663 | data += tocopy; | 667 | data += tocopy; |
664 | blk++; | 668 | blk++; |
665 | } | 669 | } |
666 | return len; | 670 | return len; |
667 | } | 671 | } |
668 | 672 | ||
669 | /* Write to quotafile */ | 673 | /* Write to quotafile */ |
670 | static ssize_t jfs_quota_write(struct super_block *sb, int type, | 674 | static ssize_t jfs_quota_write(struct super_block *sb, int type, |
671 | const char *data, size_t len, loff_t off) | 675 | const char *data, size_t len, loff_t off) |
672 | { | 676 | { |
673 | struct inode *inode = sb_dqopt(sb)->files[type]; | 677 | struct inode *inode = sb_dqopt(sb)->files[type]; |
674 | sector_t blk = off >> sb->s_blocksize_bits; | 678 | sector_t blk = off >> sb->s_blocksize_bits; |
675 | int err = 0; | 679 | int err = 0; |
676 | int offset = off & (sb->s_blocksize - 1); | 680 | int offset = off & (sb->s_blocksize - 1); |
677 | int tocopy; | 681 | int tocopy; |
678 | size_t towrite = len; | 682 | size_t towrite = len; |
679 | struct buffer_head tmp_bh; | 683 | struct buffer_head tmp_bh; |
680 | struct buffer_head *bh; | 684 | struct buffer_head *bh; |
681 | 685 | ||
682 | mutex_lock(&inode->i_mutex); | 686 | mutex_lock(&inode->i_mutex); |
683 | while (towrite > 0) { | 687 | while (towrite > 0) { |
684 | tocopy = sb->s_blocksize - offset < towrite ? | 688 | tocopy = sb->s_blocksize - offset < towrite ? |
685 | sb->s_blocksize - offset : towrite; | 689 | sb->s_blocksize - offset : towrite; |
686 | 690 | ||
687 | tmp_bh.b_state = 0; | 691 | tmp_bh.b_state = 0; |
688 | tmp_bh.b_size = 1 << inode->i_blkbits; | 692 | tmp_bh.b_size = 1 << inode->i_blkbits; |
689 | err = jfs_get_block(inode, blk, &tmp_bh, 1); | 693 | err = jfs_get_block(inode, blk, &tmp_bh, 1); |
690 | if (err) | 694 | if (err) |
691 | goto out; | 695 | goto out; |
692 | if (offset || tocopy != sb->s_blocksize) | 696 | if (offset || tocopy != sb->s_blocksize) |
693 | bh = sb_bread(sb, tmp_bh.b_blocknr); | 697 | bh = sb_bread(sb, tmp_bh.b_blocknr); |
694 | else | 698 | else |
695 | bh = sb_getblk(sb, tmp_bh.b_blocknr); | 699 | bh = sb_getblk(sb, tmp_bh.b_blocknr); |
696 | if (!bh) { | 700 | if (!bh) { |
697 | err = -EIO; | 701 | err = -EIO; |
698 | goto out; | 702 | goto out; |
699 | } | 703 | } |
700 | lock_buffer(bh); | 704 | lock_buffer(bh); |
701 | memcpy(bh->b_data+offset, data, tocopy); | 705 | memcpy(bh->b_data+offset, data, tocopy); |
702 | flush_dcache_page(bh->b_page); | 706 | flush_dcache_page(bh->b_page); |
703 | set_buffer_uptodate(bh); | 707 | set_buffer_uptodate(bh); |
704 | mark_buffer_dirty(bh); | 708 | mark_buffer_dirty(bh); |
705 | unlock_buffer(bh); | 709 | unlock_buffer(bh); |
706 | brelse(bh); | 710 | brelse(bh); |
707 | offset = 0; | 711 | offset = 0; |
708 | towrite -= tocopy; | 712 | towrite -= tocopy; |
709 | data += tocopy; | 713 | data += tocopy; |
710 | blk++; | 714 | blk++; |
711 | } | 715 | } |
712 | out: | 716 | out: |
713 | if (len == towrite) | 717 | if (len == towrite) |
714 | return err; | 718 | return err; |
715 | if (inode->i_size < off+len-towrite) | 719 | if (inode->i_size < off+len-towrite) |
716 | i_size_write(inode, off+len-towrite); | 720 | i_size_write(inode, off+len-towrite); |
717 | inode->i_version++; | 721 | inode->i_version++; |
718 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 722 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
719 | mark_inode_dirty(inode); | 723 | mark_inode_dirty(inode); |
720 | mutex_unlock(&inode->i_mutex); | 724 | mutex_unlock(&inode->i_mutex); |
721 | return len - towrite; | 725 | return len - towrite; |
722 | } | 726 | } |
723 | 727 | ||
724 | #endif | 728 | #endif |
725 | 729 | ||
726 | static const struct super_operations jfs_super_operations = { | 730 | static const struct super_operations jfs_super_operations = { |
727 | .alloc_inode = jfs_alloc_inode, | 731 | .alloc_inode = jfs_alloc_inode, |
728 | .destroy_inode = jfs_destroy_inode, | 732 | .destroy_inode = jfs_destroy_inode, |
729 | .read_inode = jfs_read_inode, | ||
730 | .dirty_inode = jfs_dirty_inode, | 733 | .dirty_inode = jfs_dirty_inode, |
731 | .write_inode = jfs_write_inode, | 734 | .write_inode = jfs_write_inode, |
732 | .delete_inode = jfs_delete_inode, | 735 | .delete_inode = jfs_delete_inode, |
733 | .put_super = jfs_put_super, | 736 | .put_super = jfs_put_super, |
734 | .sync_fs = jfs_sync_fs, | 737 | .sync_fs = jfs_sync_fs, |
735 | .write_super_lockfs = jfs_write_super_lockfs, | 738 | .write_super_lockfs = jfs_write_super_lockfs, |
736 | .unlockfs = jfs_unlockfs, | 739 | .unlockfs = jfs_unlockfs, |
737 | .statfs = jfs_statfs, | 740 | .statfs = jfs_statfs, |
738 | .remount_fs = jfs_remount, | 741 | .remount_fs = jfs_remount, |
739 | .show_options = jfs_show_options, | 742 | .show_options = jfs_show_options, |
740 | #ifdef CONFIG_QUOTA | 743 | #ifdef CONFIG_QUOTA |
741 | .quota_read = jfs_quota_read, | 744 | .quota_read = jfs_quota_read, |
742 | .quota_write = jfs_quota_write, | 745 | .quota_write = jfs_quota_write, |
743 | #endif | 746 | #endif |
744 | }; | 747 | }; |
745 | 748 | ||
746 | static const struct export_operations jfs_export_operations = { | 749 | static const struct export_operations jfs_export_operations = { |
747 | .fh_to_dentry = jfs_fh_to_dentry, | 750 | .fh_to_dentry = jfs_fh_to_dentry, |
748 | .fh_to_parent = jfs_fh_to_parent, | 751 | .fh_to_parent = jfs_fh_to_parent, |
749 | .get_parent = jfs_get_parent, | 752 | .get_parent = jfs_get_parent, |
750 | }; | 753 | }; |
751 | 754 | ||
752 | static struct file_system_type jfs_fs_type = { | 755 | static struct file_system_type jfs_fs_type = { |
753 | .owner = THIS_MODULE, | 756 | .owner = THIS_MODULE, |
754 | .name = "jfs", | 757 | .name = "jfs", |
755 | .get_sb = jfs_get_sb, | 758 | .get_sb = jfs_get_sb, |
756 | .kill_sb = kill_block_super, | 759 | .kill_sb = kill_block_super, |
757 | .fs_flags = FS_REQUIRES_DEV, | 760 | .fs_flags = FS_REQUIRES_DEV, |
758 | }; | 761 | }; |
759 | 762 | ||
760 | static void init_once(struct kmem_cache *cachep, void *foo) | 763 | static void init_once(struct kmem_cache *cachep, void *foo) |
761 | { | 764 | { |
762 | struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; | 765 | struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; |
763 | 766 | ||
764 | memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); | 767 | memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); |
765 | INIT_LIST_HEAD(&jfs_ip->anon_inode_list); | 768 | INIT_LIST_HEAD(&jfs_ip->anon_inode_list); |
766 | init_rwsem(&jfs_ip->rdwrlock); | 769 | init_rwsem(&jfs_ip->rdwrlock); |
767 | mutex_init(&jfs_ip->commit_mutex); | 770 | mutex_init(&jfs_ip->commit_mutex); |
768 | init_rwsem(&jfs_ip->xattr_sem); | 771 | init_rwsem(&jfs_ip->xattr_sem); |
769 | spin_lock_init(&jfs_ip->ag_lock); | 772 | spin_lock_init(&jfs_ip->ag_lock); |
770 | jfs_ip->active_ag = -1; | 773 | jfs_ip->active_ag = -1; |
771 | #ifdef CONFIG_JFS_POSIX_ACL | 774 | #ifdef CONFIG_JFS_POSIX_ACL |
772 | jfs_ip->i_acl = JFS_ACL_NOT_CACHED; | 775 | jfs_ip->i_acl = JFS_ACL_NOT_CACHED; |
773 | jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; | 776 | jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; |
774 | #endif | 777 | #endif |
775 | inode_init_once(&jfs_ip->vfs_inode); | 778 | inode_init_once(&jfs_ip->vfs_inode); |
776 | } | 779 | } |
777 | 780 | ||
778 | static int __init init_jfs_fs(void) | 781 | static int __init init_jfs_fs(void) |
779 | { | 782 | { |
780 | int i; | 783 | int i; |
781 | int rc; | 784 | int rc; |
782 | 785 | ||
783 | jfs_inode_cachep = | 786 | jfs_inode_cachep = |
784 | kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0, | 787 | kmem_cache_create("jfs_ip", sizeof(struct jfs_inode_info), 0, |
785 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, | 788 | SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD, |
786 | init_once); | 789 | init_once); |
787 | if (jfs_inode_cachep == NULL) | 790 | if (jfs_inode_cachep == NULL) |
788 | return -ENOMEM; | 791 | return -ENOMEM; |
789 | 792 | ||
790 | /* | 793 | /* |
791 | * Metapage initialization | 794 | * Metapage initialization |
792 | */ | 795 | */ |
793 | rc = metapage_init(); | 796 | rc = metapage_init(); |
794 | if (rc) { | 797 | if (rc) { |
795 | jfs_err("metapage_init failed w/rc = %d", rc); | 798 | jfs_err("metapage_init failed w/rc = %d", rc); |
796 | goto free_slab; | 799 | goto free_slab; |
797 | } | 800 | } |
798 | 801 | ||
799 | /* | 802 | /* |
800 | * Transaction Manager initialization | 803 | * Transaction Manager initialization |
801 | */ | 804 | */ |
802 | rc = txInit(); | 805 | rc = txInit(); |
803 | if (rc) { | 806 | if (rc) { |
804 | jfs_err("txInit failed w/rc = %d", rc); | 807 | jfs_err("txInit failed w/rc = %d", rc); |
805 | goto free_metapage; | 808 | goto free_metapage; |
806 | } | 809 | } |
807 | 810 | ||
808 | /* | 811 | /* |
809 | * I/O completion thread (endio) | 812 | * I/O completion thread (endio) |
810 | */ | 813 | */ |
811 | jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO"); | 814 | jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO"); |
812 | if (IS_ERR(jfsIOthread)) { | 815 | if (IS_ERR(jfsIOthread)) { |
813 | rc = PTR_ERR(jfsIOthread); | 816 | rc = PTR_ERR(jfsIOthread); |
814 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); | 817 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); |
815 | goto end_txmngr; | 818 | goto end_txmngr; |
816 | } | 819 | } |
817 | 820 | ||
818 | if (commit_threads < 1) | 821 | if (commit_threads < 1) |
819 | commit_threads = num_online_cpus(); | 822 | commit_threads = num_online_cpus(); |
820 | if (commit_threads > MAX_COMMIT_THREADS) | 823 | if (commit_threads > MAX_COMMIT_THREADS) |
821 | commit_threads = MAX_COMMIT_THREADS; | 824 | commit_threads = MAX_COMMIT_THREADS; |
822 | 825 | ||
823 | for (i = 0; i < commit_threads; i++) { | 826 | for (i = 0; i < commit_threads; i++) { |
824 | jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, "jfsCommit"); | 827 | jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, "jfsCommit"); |
825 | if (IS_ERR(jfsCommitThread[i])) { | 828 | if (IS_ERR(jfsCommitThread[i])) { |
826 | rc = PTR_ERR(jfsCommitThread[i]); | 829 | rc = PTR_ERR(jfsCommitThread[i]); |
827 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); | 830 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); |
828 | commit_threads = i; | 831 | commit_threads = i; |
829 | goto kill_committask; | 832 | goto kill_committask; |
830 | } | 833 | } |
831 | } | 834 | } |
832 | 835 | ||
833 | jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync"); | 836 | jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync"); |
834 | if (IS_ERR(jfsSyncThread)) { | 837 | if (IS_ERR(jfsSyncThread)) { |
835 | rc = PTR_ERR(jfsSyncThread); | 838 | rc = PTR_ERR(jfsSyncThread); |
836 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); | 839 | jfs_err("init_jfs_fs: fork failed w/rc = %d", rc); |
837 | goto kill_committask; | 840 | goto kill_committask; |
838 | } | 841 | } |
839 | 842 | ||
840 | #ifdef PROC_FS_JFS | 843 | #ifdef PROC_FS_JFS |
841 | jfs_proc_init(); | 844 | jfs_proc_init(); |
842 | #endif | 845 | #endif |
843 | 846 | ||
844 | return register_filesystem(&jfs_fs_type); | 847 | return register_filesystem(&jfs_fs_type); |
845 | 848 | ||
846 | kill_committask: | 849 | kill_committask: |
847 | for (i = 0; i < commit_threads; i++) | 850 | for (i = 0; i < commit_threads; i++) |
848 | kthread_stop(jfsCommitThread[i]); | 851 | kthread_stop(jfsCommitThread[i]); |
849 | kthread_stop(jfsIOthread); | 852 | kthread_stop(jfsIOthread); |
850 | end_txmngr: | 853 | end_txmngr: |
851 | txExit(); | 854 | txExit(); |
852 | free_metapage: | 855 | free_metapage: |
853 | metapage_exit(); | 856 | metapage_exit(); |
854 | free_slab: | 857 | free_slab: |
855 | kmem_cache_destroy(jfs_inode_cachep); | 858 | kmem_cache_destroy(jfs_inode_cachep); |
856 | return rc; | 859 | return rc; |
857 | } | 860 | } |
858 | 861 | ||
859 | static void __exit exit_jfs_fs(void) | 862 | static void __exit exit_jfs_fs(void) |
860 | { | 863 | { |
861 | int i; | 864 | int i; |
862 | 865 | ||
863 | jfs_info("exit_jfs_fs called"); | 866 | jfs_info("exit_jfs_fs called"); |
864 | 867 | ||
865 | txExit(); | 868 | txExit(); |
866 | metapage_exit(); | 869 | metapage_exit(); |
867 | 870 | ||
868 | kthread_stop(jfsIOthread); | 871 | kthread_stop(jfsIOthread); |
869 | for (i = 0; i < commit_threads; i++) | 872 | for (i = 0; i < commit_threads; i++) |
870 | kthread_stop(jfsCommitThread[i]); | 873 | kthread_stop(jfsCommitThread[i]); |
871 | kthread_stop(jfsSyncThread); | 874 | kthread_stop(jfsSyncThread); |
872 | #ifdef PROC_FS_JFS | 875 | #ifdef PROC_FS_JFS |
873 | jfs_proc_clean(); | 876 | jfs_proc_clean(); |
874 | #endif | 877 | #endif |
875 | unregister_filesystem(&jfs_fs_type); | 878 | unregister_filesystem(&jfs_fs_type); |
876 | kmem_cache_destroy(jfs_inode_cachep); | 879 | kmem_cache_destroy(jfs_inode_cachep); |
877 | } | 880 | } |
878 | 881 | ||
879 | module_init(init_jfs_fs) | 882 | module_init(init_jfs_fs) |
880 | module_exit(exit_jfs_fs) | 883 | module_exit(exit_jfs_fs) |