diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-10 13:18:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-10 13:18:27 -0500 |
commit | 41f81e88e01eb959f439f8537c58078e4bfc5291 (patch) | |
tree | 3d5dba6982a074bcd5f3248c57679215e5f8b701 /fs/xfs/linux-2.6 | |
parent | dc3d532a1792263ec9b26c1cbc7ce566056b5b1f (diff) | |
parent | cf10e82bdc0d38d09dfaf46d0daf56136138ef3f (diff) |
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6:
[XFS] Fix xfs_ichgtime()s broken usage of I_SYNC
[XFS] Make xfsbufd threads freezable
[XFS] revert to double-buffering readdir
[XFS] Fix broken inode cluster setup.
[XFS] Clear XBF_READ_AHEAD flag on I/O completion.
[XFS] Fixed a few bugs in xfs_buf_associate_memory()
[XFS] 971064 Various fixups for xfs_bulkstat().
[XFS] Fix dbflush panic in xfs_qm_sync.
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 37 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 124 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 20 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl32.c | 3 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 4 |
5 files changed, 153 insertions, 35 deletions
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index b9c8589e05c2..a49dd8d4b069 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -725,15 +725,15 @@ xfs_buf_associate_memory( | |||
725 | { | 725 | { |
726 | int rval; | 726 | int rval; |
727 | int i = 0; | 727 | int i = 0; |
728 | size_t ptr; | 728 | unsigned long pageaddr; |
729 | size_t end, end_cur; | 729 | unsigned long offset; |
730 | off_t offset; | 730 | size_t buflen; |
731 | int page_count; | 731 | int page_count; |
732 | 732 | ||
733 | page_count = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; | 733 | pageaddr = (unsigned long)mem & PAGE_CACHE_MASK; |
734 | offset = (off_t) mem - ((off_t)mem & PAGE_CACHE_MASK); | 734 | offset = (unsigned long)mem - pageaddr; |
735 | if (offset && (len > PAGE_CACHE_SIZE)) | 735 | buflen = PAGE_CACHE_ALIGN(len + offset); |
736 | page_count++; | 736 | page_count = buflen >> PAGE_CACHE_SHIFT; |
737 | 737 | ||
738 | /* Free any previous set of page pointers */ | 738 | /* Free any previous set of page pointers */ |
739 | if (bp->b_pages) | 739 | if (bp->b_pages) |
@@ -747,22 +747,15 @@ xfs_buf_associate_memory( | |||
747 | return rval; | 747 | return rval; |
748 | 748 | ||
749 | bp->b_offset = offset; | 749 | bp->b_offset = offset; |
750 | ptr = (size_t) mem & PAGE_CACHE_MASK; | 750 | |
751 | end = PAGE_CACHE_ALIGN((size_t) mem + len); | 751 | for (i = 0; i < bp->b_page_count; i++) { |
752 | end_cur = end; | 752 | bp->b_pages[i] = mem_to_page((void *)pageaddr); |
753 | /* set up first page */ | 753 | pageaddr += PAGE_CACHE_SIZE; |
754 | bp->b_pages[0] = mem_to_page(mem); | ||
755 | |||
756 | ptr += PAGE_CACHE_SIZE; | ||
757 | bp->b_page_count = ++i; | ||
758 | while (ptr < end) { | ||
759 | bp->b_pages[i] = mem_to_page((void *)ptr); | ||
760 | bp->b_page_count = ++i; | ||
761 | ptr += PAGE_CACHE_SIZE; | ||
762 | } | 754 | } |
763 | bp->b_locked = 0; | 755 | bp->b_locked = 0; |
764 | 756 | ||
765 | bp->b_count_desired = bp->b_buffer_length = len; | 757 | bp->b_count_desired = len; |
758 | bp->b_buffer_length = buflen; | ||
766 | bp->b_flags |= XBF_MAPPED; | 759 | bp->b_flags |= XBF_MAPPED; |
767 | 760 | ||
768 | return 0; | 761 | return 0; |
@@ -1032,7 +1025,7 @@ xfs_buf_ioend( | |||
1032 | xfs_buf_t *bp, | 1025 | xfs_buf_t *bp, |
1033 | int schedule) | 1026 | int schedule) |
1034 | { | 1027 | { |
1035 | bp->b_flags &= ~(XBF_READ | XBF_WRITE); | 1028 | bp->b_flags &= ~(XBF_READ | XBF_WRITE | XBF_READ_AHEAD); |
1036 | if (bp->b_error == 0) | 1029 | if (bp->b_error == 0) |
1037 | bp->b_flags |= XBF_DONE; | 1030 | bp->b_flags |= XBF_DONE; |
1038 | 1031 | ||
@@ -1750,6 +1743,8 @@ xfsbufd( | |||
1750 | 1743 | ||
1751 | current->flags |= PF_MEMALLOC; | 1744 | current->flags |= PF_MEMALLOC; |
1752 | 1745 | ||
1746 | set_freezable(); | ||
1747 | |||
1753 | do { | 1748 | do { |
1754 | if (unlikely(freezing(current))) { | 1749 | if (unlikely(freezing(current))) { |
1755 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); | 1750 | set_bit(XBT_FORCE_SLEEP, &target->bt_flags); |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index fb8dd34041eb..54c564693d93 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -218,6 +218,15 @@ xfs_vm_fault( | |||
218 | } | 218 | } |
219 | #endif /* CONFIG_XFS_DMAPI */ | 219 | #endif /* CONFIG_XFS_DMAPI */ |
220 | 220 | ||
221 | /* | ||
222 | * Unfortunately we can't just use the clean and simple readdir implementation | ||
223 | * below, because nfs might call back into ->lookup from the filldir callback | ||
224 | * and that will deadlock the low-level btree code. | ||
225 | * | ||
226 | * Hopefully we'll find a better workaround that allows to use the optimal | ||
227 | * version at least for local readdirs for 2.6.25. | ||
228 | */ | ||
229 | #if 0 | ||
221 | STATIC int | 230 | STATIC int |
222 | xfs_file_readdir( | 231 | xfs_file_readdir( |
223 | struct file *filp, | 232 | struct file *filp, |
@@ -249,6 +258,121 @@ xfs_file_readdir( | |||
249 | return -error; | 258 | return -error; |
250 | return 0; | 259 | return 0; |
251 | } | 260 | } |
261 | #else | ||
262 | |||
263 | struct hack_dirent { | ||
264 | int namlen; | ||
265 | loff_t offset; | ||
266 | u64 ino; | ||
267 | unsigned int d_type; | ||
268 | char name[]; | ||
269 | }; | ||
270 | |||
271 | struct hack_callback { | ||
272 | char *dirent; | ||
273 | size_t len; | ||
274 | size_t used; | ||
275 | }; | ||
276 | |||
277 | STATIC int | ||
278 | xfs_hack_filldir( | ||
279 | void *__buf, | ||
280 | const char *name, | ||
281 | int namlen, | ||
282 | loff_t offset, | ||
283 | u64 ino, | ||
284 | unsigned int d_type) | ||
285 | { | ||
286 | struct hack_callback *buf = __buf; | ||
287 | struct hack_dirent *de = (struct hack_dirent *)(buf->dirent + buf->used); | ||
288 | |||
289 | if (buf->used + sizeof(struct hack_dirent) + namlen > buf->len) | ||
290 | return -EINVAL; | ||
291 | |||
292 | de->namlen = namlen; | ||
293 | de->offset = offset; | ||
294 | de->ino = ino; | ||
295 | de->d_type = d_type; | ||
296 | memcpy(de->name, name, namlen); | ||
297 | buf->used += sizeof(struct hack_dirent) + namlen; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | STATIC int | ||
302 | xfs_file_readdir( | ||
303 | struct file *filp, | ||
304 | void *dirent, | ||
305 | filldir_t filldir) | ||
306 | { | ||
307 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
308 | xfs_inode_t *ip = XFS_I(inode); | ||
309 | struct hack_callback buf; | ||
310 | struct hack_dirent *de; | ||
311 | int error; | ||
312 | loff_t size; | ||
313 | int eof = 0; | ||
314 | xfs_off_t start_offset, curr_offset, offset; | ||
315 | |||
316 | /* | ||
317 | * Try fairly hard to get memory | ||
318 | */ | ||
319 | buf.len = PAGE_CACHE_SIZE; | ||
320 | do { | ||
321 | buf.dirent = kmalloc(buf.len, GFP_KERNEL); | ||
322 | if (buf.dirent) | ||
323 | break; | ||
324 | buf.len >>= 1; | ||
325 | } while (buf.len >= 1024); | ||
326 | |||
327 | if (!buf.dirent) | ||
328 | return -ENOMEM; | ||
329 | |||
330 | curr_offset = filp->f_pos; | ||
331 | if (curr_offset == 0x7fffffff) | ||
332 | offset = 0xffffffff; | ||
333 | else | ||
334 | offset = filp->f_pos; | ||
335 | |||
336 | while (!eof) { | ||
337 | int reclen; | ||
338 | start_offset = offset; | ||
339 | |||
340 | buf.used = 0; | ||
341 | error = -xfs_readdir(ip, &buf, buf.len, &offset, | ||
342 | xfs_hack_filldir); | ||
343 | if (error || offset == start_offset) { | ||
344 | size = 0; | ||
345 | break; | ||
346 | } | ||
347 | |||
348 | size = buf.used; | ||
349 | de = (struct hack_dirent *)buf.dirent; | ||
350 | while (size > 0) { | ||
351 | if (filldir(dirent, de->name, de->namlen, | ||
352 | curr_offset & 0x7fffffff, | ||
353 | de->ino, de->d_type)) { | ||
354 | goto done; | ||
355 | } | ||
356 | |||
357 | reclen = sizeof(struct hack_dirent) + de->namlen; | ||
358 | size -= reclen; | ||
359 | curr_offset = de->offset /* & 0x7fffffff */; | ||
360 | de = (struct hack_dirent *)((char *)de + reclen); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | done: | ||
365 | if (!error) { | ||
366 | if (size == 0) | ||
367 | filp->f_pos = offset & 0x7fffffff; | ||
368 | else if (de) | ||
369 | filp->f_pos = curr_offset; | ||
370 | } | ||
371 | |||
372 | kfree(buf.dirent); | ||
373 | return error; | ||
374 | } | ||
375 | #endif | ||
252 | 376 | ||
253 | STATIC int | 377 | STATIC int |
254 | xfs_file_mmap( | 378 | xfs_file_mmap( |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 2b34bad48b07..98a56568bb24 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -1047,24 +1047,20 @@ xfs_ioc_bulkstat( | |||
1047 | if ((count = bulkreq.icount) <= 0) | 1047 | if ((count = bulkreq.icount) <= 0) |
1048 | return -XFS_ERROR(EINVAL); | 1048 | return -XFS_ERROR(EINVAL); |
1049 | 1049 | ||
1050 | if (bulkreq.ubuffer == NULL) | ||
1051 | return -XFS_ERROR(EINVAL); | ||
1052 | |||
1050 | if (cmd == XFS_IOC_FSINUMBERS) | 1053 | if (cmd == XFS_IOC_FSINUMBERS) |
1051 | error = xfs_inumbers(mp, &inlast, &count, | 1054 | error = xfs_inumbers(mp, &inlast, &count, |
1052 | bulkreq.ubuffer, xfs_inumbers_fmt); | 1055 | bulkreq.ubuffer, xfs_inumbers_fmt); |
1053 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) | 1056 | else if (cmd == XFS_IOC_FSBULKSTAT_SINGLE) |
1054 | error = xfs_bulkstat_single(mp, &inlast, | 1057 | error = xfs_bulkstat_single(mp, &inlast, |
1055 | bulkreq.ubuffer, &done); | 1058 | bulkreq.ubuffer, &done); |
1056 | else { /* XFS_IOC_FSBULKSTAT */ | 1059 | else /* XFS_IOC_FSBULKSTAT */ |
1057 | if (count == 1 && inlast != 0) { | 1060 | error = xfs_bulkstat(mp, &inlast, &count, |
1058 | inlast++; | 1061 | (bulkstat_one_pf)xfs_bulkstat_one, NULL, |
1059 | error = xfs_bulkstat_single(mp, &inlast, | 1062 | sizeof(xfs_bstat_t), bulkreq.ubuffer, |
1060 | bulkreq.ubuffer, &done); | 1063 | BULKSTAT_FG_QUICK, &done); |
1061 | } else { | ||
1062 | error = xfs_bulkstat(mp, &inlast, &count, | ||
1063 | (bulkstat_one_pf)xfs_bulkstat_one, NULL, | ||
1064 | sizeof(xfs_bstat_t), bulkreq.ubuffer, | ||
1065 | BULKSTAT_FG_QUICK, &done); | ||
1066 | } | ||
1067 | } | ||
1068 | 1064 | ||
1069 | if (error) | 1065 | if (error) |
1070 | return -error; | 1066 | return -error; |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 0046bdd5b7f1..bf2a956b63c2 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -291,6 +291,9 @@ xfs_ioc_bulkstat_compat( | |||
291 | if ((count = bulkreq.icount) <= 0) | 291 | if ((count = bulkreq.icount) <= 0) |
292 | return -XFS_ERROR(EINVAL); | 292 | return -XFS_ERROR(EINVAL); |
293 | 293 | ||
294 | if (bulkreq.ubuffer == NULL) | ||
295 | return -XFS_ERROR(EINVAL); | ||
296 | |||
294 | if (cmd == XFS_IOC_FSINUMBERS) | 297 | if (cmd == XFS_IOC_FSINUMBERS) |
295 | error = xfs_inumbers(mp, &inlast, &count, | 298 | error = xfs_inumbers(mp, &inlast, &count, |
296 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); | 299 | bulkreq.ubuffer, xfs_inumbers_fmt_compat); |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index ac50f8a37582..37e116779eb1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -117,7 +117,7 @@ xfs_ichgtime( | |||
117 | */ | 117 | */ |
118 | SYNCHRONIZE(); | 118 | SYNCHRONIZE(); |
119 | ip->i_update_core = 1; | 119 | ip->i_update_core = 1; |
120 | if (!(inode->i_state & I_SYNC)) | 120 | if (!(inode->i_state & I_NEW)) |
121 | mark_inode_dirty_sync(inode); | 121 | mark_inode_dirty_sync(inode); |
122 | } | 122 | } |
123 | 123 | ||
@@ -169,7 +169,7 @@ xfs_ichgtime_fast( | |||
169 | */ | 169 | */ |
170 | SYNCHRONIZE(); | 170 | SYNCHRONIZE(); |
171 | ip->i_update_core = 1; | 171 | ip->i_update_core = 1; |
172 | if (!(inode->i_state & I_SYNC)) | 172 | if (!(inode->i_state & I_NEW)) |
173 | mark_inode_dirty_sync(inode); | 173 | mark_inode_dirty_sync(inode); |
174 | } | 174 | } |
175 | 175 | ||