diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-13 11:15:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-11-13 11:15:30 -0500 |
commit | eea2078eaf2bcd4e5e8b2e08798071efedac5e17 (patch) | |
tree | e8b9f7ea55f098c6c73d4bdca2794f40ce619476 /fs | |
parent | ea991f06d851d58268eac6ce5c2152397757c958 (diff) | |
parent | 050e714eb2bc662e9df6bf048ce86b4fbdd9bcd3 (diff) |
Merge git://oss.sgi.com:8090/xfs/xfs-2.6
* git://oss.sgi.com:8090/xfs/xfs-2.6:
[XFS] Remove KERNEL_VERSION macros from xfs_dmapi.h
[XFS] Prevent a deadlock when xfslogd unpins inodes.
[XFS] Clean up i_flags and i_flags_lock handling.
[XFS] 956664: dm_read_invis() changes i_atime
[XFS] rename uio_read() to xfs_uio_read()
[XFS] Keep lockdep happy.
[XFS] 956618: Linux crashes on boot with XFS-DMAPI filesystem when
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/Makefile-linux-2.6 | 17 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 4 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_dmapi_priv.h | 28 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_ioctl.c | 5 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 4 | ||||
-rw-r--r-- | fs/xfs/support/debug.c | 4 | ||||
-rw-r--r-- | fs/xfs/support/move.c | 2 | ||||
-rw-r--r-- | fs/xfs/support/move.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs.h | 23 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_dmapi.h | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_iget.c | 51 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.c | 64 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 41 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 33 |
15 files changed, 189 insertions, 113 deletions
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 291948d5085a..b49989bb89ad 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 | |||
@@ -21,22 +21,7 @@ EXTRA_CFLAGS += -Ifs/xfs -Ifs/xfs/linux-2.6 -funsigned-char | |||
21 | XFS_LINUX := linux-2.6 | 21 | XFS_LINUX := linux-2.6 |
22 | 22 | ||
23 | ifeq ($(CONFIG_XFS_DEBUG),y) | 23 | ifeq ($(CONFIG_XFS_DEBUG),y) |
24 | EXTRA_CFLAGS += -g -DSTATIC="" -DDEBUG | 24 | EXTRA_CFLAGS += -g |
25 | EXTRA_CFLAGS += -DXFS_BUF_LOCK_TRACKING | ||
26 | endif | ||
27 | ifeq ($(CONFIG_XFS_TRACE),y) | ||
28 | EXTRA_CFLAGS += -DXFS_ALLOC_TRACE | ||
29 | EXTRA_CFLAGS += -DXFS_ATTR_TRACE | ||
30 | EXTRA_CFLAGS += -DXFS_BLI_TRACE | ||
31 | EXTRA_CFLAGS += -DXFS_BMAP_TRACE | ||
32 | EXTRA_CFLAGS += -DXFS_BMBT_TRACE | ||
33 | EXTRA_CFLAGS += -DXFS_DIR2_TRACE | ||
34 | EXTRA_CFLAGS += -DXFS_DQUOT_TRACE | ||
35 | EXTRA_CFLAGS += -DXFS_ILOCK_TRACE | ||
36 | EXTRA_CFLAGS += -DXFS_LOG_TRACE | ||
37 | EXTRA_CFLAGS += -DXFS_RW_TRACE | ||
38 | EXTRA_CFLAGS += -DXFS_BUF_TRACE | ||
39 | EXTRA_CFLAGS += -DXFS_VNODE_TRACE | ||
40 | endif | 25 | endif |
41 | 26 | ||
42 | obj-$(CONFIG_XFS_FS) += xfs.o | 27 | obj-$(CONFIG_XFS_FS) += xfs.o |
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index db5f5a3608ca..d3382843698e 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include "xfs.h" | ||
18 | #include <linux/stddef.h> | 19 | #include <linux/stddef.h> |
19 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
@@ -31,7 +32,6 @@ | |||
31 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
32 | #include <linux/migrate.h> | 33 | #include <linux/migrate.h> |
33 | #include <linux/backing-dev.h> | 34 | #include <linux/backing-dev.h> |
34 | #include "xfs_linux.h" | ||
35 | 35 | ||
36 | STATIC kmem_zone_t *xfs_buf_zone; | 36 | STATIC kmem_zone_t *xfs_buf_zone; |
37 | STATIC kmem_shaker_t xfs_buf_shake; | 37 | STATIC kmem_shaker_t xfs_buf_shake; |
@@ -1406,7 +1406,7 @@ xfs_alloc_bufhash( | |||
1406 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ | 1406 | btp->bt_hashshift = external ? 3 : 8; /* 8 or 256 buckets */ |
1407 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; | 1407 | btp->bt_hashmask = (1 << btp->bt_hashshift) - 1; |
1408 | btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * | 1408 | btp->bt_hash = kmem_zalloc((1 << btp->bt_hashshift) * |
1409 | sizeof(xfs_bufhash_t), KM_SLEEP); | 1409 | sizeof(xfs_bufhash_t), KM_SLEEP | KM_LARGE); |
1410 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { | 1410 | for (i = 0; i < (1 << btp->bt_hashshift); i++) { |
1411 | spin_lock_init(&btp->bt_hash[i].bh_lock); | 1411 | spin_lock_init(&btp->bt_hash[i].bh_lock); |
1412 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); | 1412 | INIT_LIST_HEAD(&btp->bt_hash[i].bh_list); |
diff --git a/fs/xfs/linux-2.6/xfs_dmapi_priv.h b/fs/xfs/linux-2.6/xfs_dmapi_priv.h new file mode 100644 index 000000000000..a8b0b1685eed --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_dmapi_priv.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DMAPI_PRIV_H__ | ||
19 | #define __XFS_DMAPI_PRIV_H__ | ||
20 | |||
21 | /* | ||
22 | * Based on IO_ISDIRECT, decide which i_ flag is set. | ||
23 | */ | ||
24 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
25 | DM_FLAGS_IMUX : 0) | ||
26 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
27 | |||
28 | #endif /*__XFS_DMAPI_PRIV_H__*/ | ||
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index a74f854d91e6..74d094829a4d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -341,8 +341,11 @@ xfs_open_by_handle( | |||
341 | put_unused_fd(new_fd); | 341 | put_unused_fd(new_fd); |
342 | return -XFS_ERROR(-PTR_ERR(filp)); | 342 | return -XFS_ERROR(-PTR_ERR(filp)); |
343 | } | 343 | } |
344 | if (inode->i_mode & S_IFREG) | 344 | if (inode->i_mode & S_IFREG) { |
345 | /* invisible operation should not change atime */ | ||
346 | filp->f_flags |= O_NOATIME; | ||
345 | filp->f_op = &xfs_invis_file_operations; | 347 | filp->f_op = &xfs_invis_file_operations; |
348 | } | ||
346 | 349 | ||
347 | fd_install(new_fd, filp); | 350 | fd_install(new_fd, filp); |
348 | return new_fd; | 351 | return new_fd; |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 38c4d128a8c0..de05abbbe7fd 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -227,9 +227,7 @@ xfs_initialize_vnode( | |||
227 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); | 227 | xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); |
228 | xfs_set_inodeops(inode); | 228 | xfs_set_inodeops(inode); |
229 | 229 | ||
230 | spin_lock(&ip->i_flags_lock); | 230 | xfs_iflags_clear(ip, XFS_INEW); |
231 | ip->i_flags &= ~XFS_INEW; | ||
232 | spin_unlock(&ip->i_flags_lock); | ||
233 | barrier(); | 231 | barrier(); |
234 | 232 | ||
235 | unlock_new_inode(inode); | 233 | unlock_new_inode(inode); |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index c75f68361e33..4363512d2f90 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -15,11 +15,9 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | #include <xfs.h> | ||
18 | #include "debug.h" | 19 | #include "debug.h" |
19 | #include "spin.h" | 20 | #include "spin.h" |
20 | #include <asm/page.h> | ||
21 | #include <linux/sched.h> | ||
22 | #include <linux/kernel.h> | ||
23 | 21 | ||
24 | static char message[256]; /* keep it off the stack */ | 22 | static char message[256]; /* keep it off the stack */ |
25 | static DEFINE_SPINLOCK(xfs_err_lock); | 23 | static DEFINE_SPINLOCK(xfs_err_lock); |
diff --git a/fs/xfs/support/move.c b/fs/xfs/support/move.c index caefa17b80fe..ac8617ca3909 100644 --- a/fs/xfs/support/move.c +++ b/fs/xfs/support/move.c | |||
@@ -22,7 +22,7 @@ | |||
22 | * as we go. | 22 | * as we go. |
23 | */ | 23 | */ |
24 | int | 24 | int |
25 | uio_read(caddr_t src, size_t len, struct uio *uio) | 25 | xfs_uio_read(caddr_t src, size_t len, struct uio *uio) |
26 | { | 26 | { |
27 | size_t count; | 27 | size_t count; |
28 | 28 | ||
diff --git a/fs/xfs/support/move.h b/fs/xfs/support/move.h index 97a2498d2da3..977879c24ff5 100644 --- a/fs/xfs/support/move.h +++ b/fs/xfs/support/move.h | |||
@@ -65,6 +65,6 @@ struct uio { | |||
65 | typedef struct uio uio_t; | 65 | typedef struct uio uio_t; |
66 | typedef struct iovec iovec_t; | 66 | typedef struct iovec iovec_t; |
67 | 67 | ||
68 | extern int uio_read (caddr_t, size_t, uio_t *); | 68 | extern int xfs_uio_read (caddr_t, size_t, uio_t *); |
69 | 69 | ||
70 | #endif /* __XFS_SUPPORT_MOVE_H__ */ | 70 | #endif /* __XFS_SUPPORT_MOVE_H__ */ |
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 1a48dbb902a7..bf0a12040b13 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h | |||
@@ -17,5 +17,28 @@ | |||
17 | */ | 17 | */ |
18 | #ifndef __XFS_H__ | 18 | #ifndef __XFS_H__ |
19 | #define __XFS_H__ | 19 | #define __XFS_H__ |
20 | |||
21 | #ifdef CONFIG_XFS_DEBUG | ||
22 | #define STATIC | ||
23 | #define DEBUG 1 | ||
24 | #define XFS_BUF_LOCK_TRACKING 1 | ||
25 | /* #define QUOTADEBUG 1 */ | ||
26 | #endif | ||
27 | |||
28 | #ifdef CONFIG_XFS_TRACE | ||
29 | #define XFS_ALLOC_TRACE 1 | ||
30 | #define XFS_ATTR_TRACE 1 | ||
31 | #define XFS_BLI_TRACE 1 | ||
32 | #define XFS_BMAP_TRACE 1 | ||
33 | #define XFS_BMBT_TRACE 1 | ||
34 | #define XFS_DIR2_TRACE 1 | ||
35 | #define XFS_DQUOT_TRACE 1 | ||
36 | #define XFS_ILOCK_TRACE 1 | ||
37 | #define XFS_LOG_TRACE 1 | ||
38 | #define XFS_RW_TRACE 1 | ||
39 | #define XFS_BUF_TRACE 1 | ||
40 | #define XFS_VNODE_TRACE 1 | ||
41 | #endif | ||
42 | |||
20 | #include <linux-2.6/xfs_linux.h> | 43 | #include <linux-2.6/xfs_linux.h> |
21 | #endif /* __XFS_H__ */ | 44 | #endif /* __XFS_H__ */ |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 8edbe1adb95b..8e8e5279334a 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -678,7 +678,7 @@ xfs_dir2_put_dirent64_uio( | |||
678 | idbp->d_off = pa->cook; | 678 | idbp->d_off = pa->cook; |
679 | idbp->d_name[namelen] = '\0'; | 679 | idbp->d_name[namelen] = '\0'; |
680 | memcpy(idbp->d_name, pa->name, namelen); | 680 | memcpy(idbp->d_name, pa->name, namelen); |
681 | rval = uio_read((caddr_t)idbp, reclen, uio); | 681 | rval = xfs_uio_read((caddr_t)idbp, reclen, uio); |
682 | pa->done = (rval == 0); | 682 | pa->done = (rval == 0); |
683 | return rval; | 683 | return rval; |
684 | } | 684 | } |
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 4e7865ad6f0e..adc3d251240d 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h | |||
@@ -157,27 +157,9 @@ typedef enum { | |||
157 | #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ | 157 | #define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */ |
158 | 158 | ||
159 | /* | 159 | /* |
160 | * Based on IO_ISDIRECT, decide which i_ flag is set. | 160 | * Pull in platform specific event flags defines |
161 | */ | 161 | */ |
162 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) | 162 | #include "xfs_dmapi_priv.h" |
163 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
164 | DM_FLAGS_IMUX : 0) | ||
165 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
166 | #endif | ||
167 | |||
168 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \ | ||
169 | (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)) | ||
170 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
171 | DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_IMUX) | ||
172 | #define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_IMUX) | ||
173 | #endif | ||
174 | |||
175 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21) | ||
176 | #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \ | ||
177 | 0 : DM_FLAGS_IMUX) | ||
178 | #define DM_SEM_FLAG_WR (DM_FLAGS_IMUX) | ||
179 | #endif | ||
180 | |||
181 | 163 | ||
182 | /* | 164 | /* |
183 | * Macros to turn caller specified delay/block flags into | 165 | * Macros to turn caller specified delay/block flags into |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b73d216ecaf9..c1c89dac19cc 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -215,7 +215,7 @@ again: | |||
215 | * If INEW is set this inode is being set up | 215 | * If INEW is set this inode is being set up |
216 | * we need to pause and try again. | 216 | * we need to pause and try again. |
217 | */ | 217 | */ |
218 | if (ip->i_flags & XFS_INEW) { | 218 | if (xfs_iflags_test(ip, XFS_INEW)) { |
219 | read_unlock(&ih->ih_lock); | 219 | read_unlock(&ih->ih_lock); |
220 | delay(1); | 220 | delay(1); |
221 | XFS_STATS_INC(xs_ig_frecycle); | 221 | XFS_STATS_INC(xs_ig_frecycle); |
@@ -230,22 +230,50 @@ again: | |||
230 | * on its way out of the system, | 230 | * on its way out of the system, |
231 | * we need to pause and try again. | 231 | * we need to pause and try again. |
232 | */ | 232 | */ |
233 | if (ip->i_flags & XFS_IRECLAIM) { | 233 | if (xfs_iflags_test(ip, XFS_IRECLAIM)) { |
234 | read_unlock(&ih->ih_lock); | 234 | read_unlock(&ih->ih_lock); |
235 | delay(1); | 235 | delay(1); |
236 | XFS_STATS_INC(xs_ig_frecycle); | 236 | XFS_STATS_INC(xs_ig_frecycle); |
237 | 237 | ||
238 | goto again; | 238 | goto again; |
239 | } | 239 | } |
240 | ASSERT(xfs_iflags_test(ip, XFS_IRECLAIMABLE)); | ||
241 | |||
242 | /* | ||
243 | * If lookup is racing with unlink, then we | ||
244 | * should return an error immediately so we | ||
245 | * don't remove it from the reclaim list and | ||
246 | * potentially leak the inode. | ||
247 | */ | ||
248 | if ((ip->i_d.di_mode == 0) && | ||
249 | !(flags & XFS_IGET_CREATE)) { | ||
250 | read_unlock(&ih->ih_lock); | ||
251 | return ENOENT; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * There may be transactions sitting in the | ||
256 | * incore log buffers or being flushed to disk | ||
257 | * at this time. We can't clear the | ||
258 | * XFS_IRECLAIMABLE flag until these | ||
259 | * transactions have hit the disk, otherwise we | ||
260 | * will void the guarantee the flag provides | ||
261 | * xfs_iunpin() | ||
262 | */ | ||
263 | if (xfs_ipincount(ip)) { | ||
264 | read_unlock(&ih->ih_lock); | ||
265 | xfs_log_force(mp, 0, | ||
266 | XFS_LOG_FORCE|XFS_LOG_SYNC); | ||
267 | XFS_STATS_INC(xs_ig_frecycle); | ||
268 | goto again; | ||
269 | } | ||
240 | 270 | ||
241 | vn_trace_exit(vp, "xfs_iget.alloc", | 271 | vn_trace_exit(vp, "xfs_iget.alloc", |
242 | (inst_t *)__return_address); | 272 | (inst_t *)__return_address); |
243 | 273 | ||
244 | XFS_STATS_INC(xs_ig_found); | 274 | XFS_STATS_INC(xs_ig_found); |
245 | 275 | ||
246 | spin_lock(&ip->i_flags_lock); | 276 | xfs_iflags_clear(ip, XFS_IRECLAIMABLE); |
247 | ip->i_flags &= ~XFS_IRECLAIMABLE; | ||
248 | spin_unlock(&ip->i_flags_lock); | ||
249 | version = ih->ih_version; | 277 | version = ih->ih_version; |
250 | read_unlock(&ih->ih_lock); | 278 | read_unlock(&ih->ih_lock); |
251 | xfs_ihash_promote(ih, ip, version); | 279 | xfs_ihash_promote(ih, ip, version); |
@@ -299,10 +327,7 @@ finish_inode: | |||
299 | if (lock_flags != 0) | 327 | if (lock_flags != 0) |
300 | xfs_ilock(ip, lock_flags); | 328 | xfs_ilock(ip, lock_flags); |
301 | 329 | ||
302 | spin_lock(&ip->i_flags_lock); | 330 | xfs_iflags_clear(ip, XFS_ISTALE); |
303 | ip->i_flags &= ~XFS_ISTALE; | ||
304 | spin_unlock(&ip->i_flags_lock); | ||
305 | |||
306 | vn_trace_exit(vp, "xfs_iget.found", | 331 | vn_trace_exit(vp, "xfs_iget.found", |
307 | (inst_t *)__return_address); | 332 | (inst_t *)__return_address); |
308 | goto return_ip; | 333 | goto return_ip; |
@@ -371,10 +396,7 @@ finish_inode: | |||
371 | ih->ih_next = ip; | 396 | ih->ih_next = ip; |
372 | ip->i_udquot = ip->i_gdquot = NULL; | 397 | ip->i_udquot = ip->i_gdquot = NULL; |
373 | ih->ih_version++; | 398 | ih->ih_version++; |
374 | spin_lock(&ip->i_flags_lock); | 399 | xfs_iflags_set(ip, XFS_INEW); |
375 | ip->i_flags |= XFS_INEW; | ||
376 | spin_unlock(&ip->i_flags_lock); | ||
377 | |||
378 | write_unlock(&ih->ih_lock); | 400 | write_unlock(&ih->ih_lock); |
379 | 401 | ||
380 | /* | 402 | /* |
@@ -625,7 +647,7 @@ xfs_iput_new(xfs_inode_t *ip, | |||
625 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); | 647 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); |
626 | 648 | ||
627 | if ((ip->i_d.di_mode == 0)) { | 649 | if ((ip->i_d.di_mode == 0)) { |
628 | ASSERT(!(ip->i_flags & XFS_IRECLAIMABLE)); | 650 | ASSERT(!xfs_iflags_test(ip, XFS_IRECLAIMABLE)); |
629 | vn_mark_bad(vp); | 651 | vn_mark_bad(vp); |
630 | } | 652 | } |
631 | if (inode->i_state & I_NEW) | 653 | if (inode->i_state & I_NEW) |
@@ -683,6 +705,7 @@ xfs_ireclaim(xfs_inode_t *ip) | |||
683 | /* | 705 | /* |
684 | * Free all memory associated with the inode. | 706 | * Free all memory associated with the inode. |
685 | */ | 707 | */ |
708 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
686 | xfs_idestroy(ip); | 709 | xfs_idestroy(ip); |
687 | } | 710 | } |
688 | 711 | ||
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c27d7d495aa0..d72c80dbfbb1 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -2193,7 +2193,7 @@ xfs_ifree_cluster( | |||
2193 | /* Inode not in memory or we found it already, | 2193 | /* Inode not in memory or we found it already, |
2194 | * nothing to do | 2194 | * nothing to do |
2195 | */ | 2195 | */ |
2196 | if (!ip || (ip->i_flags & XFS_ISTALE)) { | 2196 | if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { |
2197 | read_unlock(&ih->ih_lock); | 2197 | read_unlock(&ih->ih_lock); |
2198 | continue; | 2198 | continue; |
2199 | } | 2199 | } |
@@ -2215,10 +2215,7 @@ xfs_ifree_cluster( | |||
2215 | 2215 | ||
2216 | if (ip == free_ip) { | 2216 | if (ip == free_ip) { |
2217 | if (xfs_iflock_nowait(ip)) { | 2217 | if (xfs_iflock_nowait(ip)) { |
2218 | spin_lock(&ip->i_flags_lock); | 2218 | xfs_iflags_set(ip, XFS_ISTALE); |
2219 | ip->i_flags |= XFS_ISTALE; | ||
2220 | spin_unlock(&ip->i_flags_lock); | ||
2221 | |||
2222 | if (xfs_inode_clean(ip)) { | 2219 | if (xfs_inode_clean(ip)) { |
2223 | xfs_ifunlock(ip); | 2220 | xfs_ifunlock(ip); |
2224 | } else { | 2221 | } else { |
@@ -2231,9 +2228,7 @@ xfs_ifree_cluster( | |||
2231 | 2228 | ||
2232 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { | 2229 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { |
2233 | if (xfs_iflock_nowait(ip)) { | 2230 | if (xfs_iflock_nowait(ip)) { |
2234 | spin_lock(&ip->i_flags_lock); | 2231 | xfs_iflags_set(ip, XFS_ISTALE); |
2235 | ip->i_flags |= XFS_ISTALE; | ||
2236 | spin_unlock(&ip->i_flags_lock); | ||
2237 | 2232 | ||
2238 | if (xfs_inode_clean(ip)) { | 2233 | if (xfs_inode_clean(ip)) { |
2239 | xfs_ifunlock(ip); | 2234 | xfs_ifunlock(ip); |
@@ -2263,9 +2258,7 @@ xfs_ifree_cluster( | |||
2263 | AIL_LOCK(mp,s); | 2258 | AIL_LOCK(mp,s); |
2264 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2259 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
2265 | AIL_UNLOCK(mp, s); | 2260 | AIL_UNLOCK(mp, s); |
2266 | spin_lock(&iip->ili_inode->i_flags_lock); | 2261 | xfs_iflags_set(ip, XFS_ISTALE); |
2267 | iip->ili_inode->i_flags |= XFS_ISTALE; | ||
2268 | spin_unlock(&iip->ili_inode->i_flags_lock); | ||
2269 | pre_flushed++; | 2262 | pre_flushed++; |
2270 | } | 2263 | } |
2271 | lip = lip->li_bio_list; | 2264 | lip = lip->li_bio_list; |
@@ -2748,42 +2741,39 @@ xfs_iunpin( | |||
2748 | { | 2741 | { |
2749 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 2742 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
2750 | 2743 | ||
2751 | if (atomic_dec_and_test(&ip->i_pincount)) { | 2744 | if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { |
2745 | |||
2752 | /* | 2746 | /* |
2753 | * If the inode is currently being reclaimed, the | 2747 | * If the inode is currently being reclaimed, the link between |
2754 | * linux inode _and_ the xfs vnode may have been | 2748 | * the bhv_vnode and the xfs_inode will be broken after the |
2755 | * freed so we cannot reference either of them safely. | 2749 | * XFS_IRECLAIM* flag is set. Hence, if these flags are not |
2756 | * Hence we should not try to do anything to them | 2750 | * set, then we can move forward and mark the linux inode dirty |
2757 | * if the xfs inode is currently in the reclaim | 2751 | * knowing that it is still valid as it won't freed until after |
2758 | * path. | 2752 | * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The |
2753 | * i_flags_lock is used to synchronise the setting of the | ||
2754 | * XFS_IRECLAIM* flags and the breaking of the link, and so we | ||
2755 | * can execute atomically w.r.t to reclaim by holding this lock | ||
2756 | * here. | ||
2759 | * | 2757 | * |
2760 | * However, we still need to issue the unpin wakeup | 2758 | * However, we still need to issue the unpin wakeup call as the |
2761 | * call as the inode reclaim may be blocked waiting for | 2759 | * inode reclaim may be blocked waiting for the inode to become |
2762 | * the inode to become unpinned. | 2760 | * unpinned. |
2763 | */ | 2761 | */ |
2764 | struct inode *inode = NULL; | ||
2765 | 2762 | ||
2766 | spin_lock(&ip->i_flags_lock); | 2763 | if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { |
2767 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { | ||
2768 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); | 2764 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); |
2765 | struct inode *inode = NULL; | ||
2766 | |||
2767 | BUG_ON(vp == NULL); | ||
2768 | inode = vn_to_inode(vp); | ||
2769 | BUG_ON(inode->i_state & I_CLEAR); | ||
2769 | 2770 | ||
2770 | /* make sync come back and flush this inode */ | 2771 | /* make sync come back and flush this inode */ |
2771 | if (vp) { | 2772 | if (!(inode->i_state & (I_NEW|I_FREEING))) |
2772 | inode = vn_to_inode(vp); | 2773 | mark_inode_dirty_sync(inode); |
2773 | |||
2774 | if (!(inode->i_state & | ||
2775 | (I_NEW|I_FREEING|I_CLEAR))) { | ||
2776 | inode = igrab(inode); | ||
2777 | if (inode) | ||
2778 | mark_inode_dirty_sync(inode); | ||
2779 | } else | ||
2780 | inode = NULL; | ||
2781 | } | ||
2782 | } | 2774 | } |
2783 | spin_unlock(&ip->i_flags_lock); | 2775 | spin_unlock(&ip->i_flags_lock); |
2784 | wake_up(&ip->i_ipin_wait); | 2776 | wake_up(&ip->i_ipin_wait); |
2785 | if (inode) | ||
2786 | iput(inode); | ||
2787 | } | 2777 | } |
2788 | } | 2778 | } |
2789 | 2779 | ||
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e96eb0835fe6..bc823720d88f 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -305,6 +305,47 @@ typedef struct xfs_inode { | |||
305 | #endif | 305 | #endif |
306 | } xfs_inode_t; | 306 | } xfs_inode_t; |
307 | 307 | ||
308 | |||
309 | /* | ||
310 | * i_flags helper functions | ||
311 | */ | ||
312 | static inline void | ||
313 | __xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) | ||
314 | { | ||
315 | ip->i_flags |= flags; | ||
316 | } | ||
317 | |||
318 | static inline void | ||
319 | xfs_iflags_set(xfs_inode_t *ip, unsigned short flags) | ||
320 | { | ||
321 | spin_lock(&ip->i_flags_lock); | ||
322 | __xfs_iflags_set(ip, flags); | ||
323 | spin_unlock(&ip->i_flags_lock); | ||
324 | } | ||
325 | |||
326 | static inline void | ||
327 | xfs_iflags_clear(xfs_inode_t *ip, unsigned short flags) | ||
328 | { | ||
329 | spin_lock(&ip->i_flags_lock); | ||
330 | ip->i_flags &= ~flags; | ||
331 | spin_unlock(&ip->i_flags_lock); | ||
332 | } | ||
333 | |||
334 | static inline int | ||
335 | __xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) | ||
336 | { | ||
337 | return (ip->i_flags & flags); | ||
338 | } | ||
339 | |||
340 | static inline int | ||
341 | xfs_iflags_test(xfs_inode_t *ip, unsigned short flags) | ||
342 | { | ||
343 | int ret; | ||
344 | spin_lock(&ip->i_flags_lock); | ||
345 | ret = __xfs_iflags_test(ip, flags); | ||
346 | spin_unlock(&ip->i_flags_lock); | ||
347 | return ret; | ||
348 | } | ||
308 | #endif /* __KERNEL__ */ | 349 | #endif /* __KERNEL__ */ |
309 | 350 | ||
310 | 351 | ||
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 061e2ffdd1de..bda774a04b8f 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1013,7 +1013,7 @@ xfs_readlink( | |||
1013 | pathlen = (int)ip->i_d.di_size; | 1013 | pathlen = (int)ip->i_d.di_size; |
1014 | 1014 | ||
1015 | if (ip->i_df.if_flags & XFS_IFINLINE) { | 1015 | if (ip->i_df.if_flags & XFS_IFINLINE) { |
1016 | error = uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); | 1016 | error = xfs_uio_read(ip->i_df.if_u1.if_data, pathlen, uiop); |
1017 | } | 1017 | } |
1018 | else { | 1018 | else { |
1019 | /* | 1019 | /* |
@@ -1044,7 +1044,7 @@ xfs_readlink( | |||
1044 | byte_cnt = pathlen; | 1044 | byte_cnt = pathlen; |
1045 | pathlen -= byte_cnt; | 1045 | pathlen -= byte_cnt; |
1046 | 1046 | ||
1047 | error = uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); | 1047 | error = xfs_uio_read(XFS_BUF_PTR(bp), byte_cnt, uiop); |
1048 | xfs_buf_relse (bp); | 1048 | xfs_buf_relse (bp); |
1049 | } | 1049 | } |
1050 | 1050 | ||
@@ -3827,11 +3827,16 @@ xfs_reclaim( | |||
3827 | */ | 3827 | */ |
3828 | xfs_synchronize_atime(ip); | 3828 | xfs_synchronize_atime(ip); |
3829 | 3829 | ||
3830 | /* If we have nothing to flush with this inode then complete the | 3830 | /* |
3831 | * teardown now, otherwise break the link between the xfs inode | 3831 | * If we have nothing to flush with this inode then complete the |
3832 | * and the linux inode and clean up the xfs inode later. This | 3832 | * teardown now, otherwise break the link between the xfs inode and the |
3833 | * avoids flushing the inode to disk during the delete operation | 3833 | * linux inode and clean up the xfs inode later. This avoids flushing |
3834 | * itself. | 3834 | * the inode to disk during the delete operation itself. |
3835 | * | ||
3836 | * When breaking the link, we need to set the XFS_IRECLAIMABLE flag | ||
3837 | * first to ensure that xfs_iunpin() will never see an xfs inode | ||
3838 | * that has a linux inode being reclaimed. Synchronisation is provided | ||
3839 | * by the i_flags_lock. | ||
3835 | */ | 3840 | */ |
3836 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { | 3841 | if (!ip->i_update_core && (ip->i_itemp == NULL)) { |
3837 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 3842 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
@@ -3840,13 +3845,13 @@ xfs_reclaim( | |||
3840 | } else { | 3845 | } else { |
3841 | xfs_mount_t *mp = ip->i_mount; | 3846 | xfs_mount_t *mp = ip->i_mount; |
3842 | 3847 | ||
3843 | /* Protect sync from us */ | 3848 | /* Protect sync and unpin from us */ |
3844 | XFS_MOUNT_ILOCK(mp); | 3849 | XFS_MOUNT_ILOCK(mp); |
3845 | vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); | ||
3846 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); | ||
3847 | spin_lock(&ip->i_flags_lock); | 3850 | spin_lock(&ip->i_flags_lock); |
3848 | ip->i_flags |= XFS_IRECLAIMABLE; | 3851 | __xfs_iflags_set(ip, XFS_IRECLAIMABLE); |
3852 | vn_bhv_remove(VN_BHV_HEAD(vp), XFS_ITOBHV(ip)); | ||
3849 | spin_unlock(&ip->i_flags_lock); | 3853 | spin_unlock(&ip->i_flags_lock); |
3854 | list_add_tail(&ip->i_reclaim, &mp->m_del_inodes); | ||
3850 | XFS_MOUNT_IUNLOCK(mp); | 3855 | XFS_MOUNT_IUNLOCK(mp); |
3851 | } | 3856 | } |
3852 | return 0; | 3857 | return 0; |
@@ -3872,8 +3877,8 @@ xfs_finish_reclaim( | |||
3872 | */ | 3877 | */ |
3873 | write_lock(&ih->ih_lock); | 3878 | write_lock(&ih->ih_lock); |
3874 | spin_lock(&ip->i_flags_lock); | 3879 | spin_lock(&ip->i_flags_lock); |
3875 | if ((ip->i_flags & XFS_IRECLAIM) || | 3880 | if (__xfs_iflags_test(ip, XFS_IRECLAIM) || |
3876 | (!(ip->i_flags & XFS_IRECLAIMABLE) && vp == NULL)) { | 3881 | (!__xfs_iflags_test(ip, XFS_IRECLAIMABLE) && vp == NULL)) { |
3877 | spin_unlock(&ip->i_flags_lock); | 3882 | spin_unlock(&ip->i_flags_lock); |
3878 | write_unlock(&ih->ih_lock); | 3883 | write_unlock(&ih->ih_lock); |
3879 | if (locked) { | 3884 | if (locked) { |
@@ -3882,7 +3887,7 @@ xfs_finish_reclaim( | |||
3882 | } | 3887 | } |
3883 | return 1; | 3888 | return 1; |
3884 | } | 3889 | } |
3885 | ip->i_flags |= XFS_IRECLAIM; | 3890 | __xfs_iflags_set(ip, XFS_IRECLAIM); |
3886 | spin_unlock(&ip->i_flags_lock); | 3891 | spin_unlock(&ip->i_flags_lock); |
3887 | write_unlock(&ih->ih_lock); | 3892 | write_unlock(&ih->ih_lock); |
3888 | 3893 | ||