diff options
author | Joern Engel <joern@wohnheim.fh-wedel.de> | 2007-10-17 02:30:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-17 11:43:02 -0400 |
commit | 1c0eeaf5698597146ed9b873e2f9e0961edcf0f9 (patch) | |
tree | 5265eac8437e8ce517a62db8fe2bd99db5b7019b /include/linux | |
parent | 2e6883bdf49abd0e7f0d9b6297fc3be7ebb2250b (diff) |
introduce I_SYNC
I_LOCK was used for several unrelated purposes, which caused deadlock
situations in certain filesystems as a side effect. One of the purposes
now uses the new I_SYNC bit.
Also document the various bits and change their order from historical to
logical.
[bunk@stusta.de: make fs/inode.c:wake_up_inode() static]
Signed-off-by: Joern Engel <joern@wohnheim.fh-wedel.de>
Cc: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: David Chinner <dgc@sgi.com>
Cc: Anton Altaparmakov <aia21@cam.ac.uk>
Cc: Al Viro <viro@ftp.linux.org.uk>
Cc: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/fs.h | 70 | ||||
-rw-r--r-- | include/linux/writeback.h | 8 |
2 files changed, 68 insertions, 10 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h index b70331f9f5b7..365586a4c4de 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1261,16 +1261,68 @@ struct super_operations { | |||
1261 | #endif | 1261 | #endif |
1262 | }; | 1262 | }; |
1263 | 1263 | ||
1264 | /* Inode state bits. Protected by inode_lock. */ | 1264 | /* |
1265 | #define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ | 1265 | * Inode state bits. Protected by inode_lock. |
1266 | #define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ | 1266 | * |
1267 | #define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ | 1267 | * Three bits determine the dirty state of the inode, I_DIRTY_SYNC, |
1268 | #define __I_LOCK 3 | 1268 | * I_DIRTY_DATASYNC and I_DIRTY_PAGES. |
1269 | * | ||
1270 | * Four bits define the lifetime of an inode. Initially, inodes are I_NEW, | ||
1271 | * until that flag is cleared. I_WILL_FREE, I_FREEING and I_CLEAR are set at | ||
1272 | * various stages of removing an inode. | ||
1273 | * | ||
1274 | * Two bits are used for locking and completion notification, I_LOCK and I_SYNC. | ||
1275 | * | ||
1276 | * I_DIRTY_SYNC Inode itself is dirty. | ||
1277 | * I_DIRTY_DATASYNC Data-related inode changes pending | ||
1278 | * I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean. | ||
1279 | * I_NEW get_new_inode() sets i_state to I_LOCK|I_NEW. Both | ||
1280 | * are cleared by unlock_new_inode(), called from iget(). | ||
1281 | * I_WILL_FREE Must be set when calling write_inode_now() if i_count | ||
1282 | * is zero. I_FREEING must be set when I_WILL_FREE is | ||
1283 | * cleared. | ||
1284 | * I_FREEING Set when inode is about to be freed but still has dirty | ||
1285 | * pages or buffers attached or the inode itself is still | ||
1286 | * dirty. | ||
1287 | * I_CLEAR Set by clear_inode(). In this state the inode is clean | ||
1288 | * and can be destroyed. | ||
1289 | * | ||
1290 | * Inodes that are I_WILL_FREE, I_FREEING or I_CLEAR are | ||
1291 | * prohibited for many purposes. iget() must wait for | ||
1292 | * the inode to be completely released, then create it | ||
1293 | * anew. Other functions will just ignore such inodes, | ||
1294 | * if appropriate. I_LOCK is used for waiting. | ||
1295 | * | ||
1296 | * I_LOCK Serves as both a mutex and completion notification. | ||
1297 | * New inodes set I_LOCK. If two processes both create | ||
1298 | * the same inode, one of them will release its inode and | ||
1299 | * wait for I_LOCK to be released before returning. | ||
1300 | * Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can | ||
1301 | * also cause waiting on I_LOCK, without I_LOCK actually | ||
1302 | * being set. find_inode() uses this to prevent returning | ||
1303 | * nearly-dead inodes. | ||
1304 | * I_SYNC Similar to I_LOCK, but limited in scope to writeback | ||
1305 | * of inode dirty data. Having a seperate lock for this | ||
1306 | * purpose reduces latency and prevents some filesystem- | ||
1307 | * specific deadlocks. | ||
1308 | * | ||
1309 | * Q: Why does I_DIRTY_DATASYNC exist? It appears as if it could be replaced | ||
1310 | * by (I_DIRTY_SYNC|I_DIRTY_PAGES). | ||
1311 | * Q: What is the difference between I_WILL_FREE and I_FREEING? | ||
1312 | * Q: igrab() only checks on (I_FREEING|I_WILL_FREE). Should it also check on | ||
1313 | * I_CLEAR? If not, why? | ||
1314 | */ | ||
1315 | #define I_DIRTY_SYNC 1 | ||
1316 | #define I_DIRTY_DATASYNC 2 | ||
1317 | #define I_DIRTY_PAGES 4 | ||
1318 | #define I_NEW 8 | ||
1319 | #define I_WILL_FREE 16 | ||
1320 | #define I_FREEING 32 | ||
1321 | #define I_CLEAR 64 | ||
1322 | #define __I_LOCK 7 | ||
1269 | #define I_LOCK (1 << __I_LOCK) | 1323 | #define I_LOCK (1 << __I_LOCK) |
1270 | #define I_FREEING 16 | 1324 | #define __I_SYNC 8 |
1271 | #define I_CLEAR 32 | 1325 | #define I_SYNC (1 << __I_SYNC) |
1272 | #define I_NEW 64 | ||
1273 | #define I_WILL_FREE 128 | ||
1274 | 1326 | ||
1275 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) | 1327 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) |
1276 | 1328 | ||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 1200868a5dee..bef7d66601cb 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
@@ -69,7 +69,6 @@ struct writeback_control { | |||
69 | * fs/fs-writeback.c | 69 | * fs/fs-writeback.c |
70 | */ | 70 | */ |
71 | void writeback_inodes(struct writeback_control *wbc); | 71 | void writeback_inodes(struct writeback_control *wbc); |
72 | void wake_up_inode(struct inode *inode); | ||
73 | int inode_wait(void *); | 72 | int inode_wait(void *); |
74 | void sync_inodes_sb(struct super_block *, int wait); | 73 | void sync_inodes_sb(struct super_block *, int wait); |
75 | void sync_inodes(int wait); | 74 | void sync_inodes(int wait); |
@@ -81,6 +80,13 @@ static inline void wait_on_inode(struct inode *inode) | |||
81 | wait_on_bit(&inode->i_state, __I_LOCK, inode_wait, | 80 | wait_on_bit(&inode->i_state, __I_LOCK, inode_wait, |
82 | TASK_UNINTERRUPTIBLE); | 81 | TASK_UNINTERRUPTIBLE); |
83 | } | 82 | } |
83 | static inline void inode_sync_wait(struct inode *inode) | ||
84 | { | ||
85 | might_sleep(); | ||
86 | wait_on_bit(&inode->i_state, __I_SYNC, inode_wait, | ||
87 | TASK_UNINTERRUPTIBLE); | ||
88 | } | ||
89 | |||
84 | 90 | ||
85 | /* | 91 | /* |
86 | * mm/page-writeback.c | 92 | * mm/page-writeback.c |