diff options
| -rw-r--r-- | fs/attr.c | 5 | ||||
| -rw-r--r-- | fs/direct-io.c | 65 | ||||
| -rw-r--r-- | fs/inode.c | 3 | ||||
| -rw-r--r-- | fs/ntfs/file.c | 3 | ||||
| -rw-r--r-- | fs/ntfs/inode.c | 10 | ||||
| -rw-r--r-- | fs/ocfs2/aops.c | 7 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 15 | ||||
| -rw-r--r-- | fs/reiserfs/xattr.c | 3 | ||||
| -rw-r--r-- | include/linux/fs.h | 11 | ||||
| -rw-r--r-- | mm/filemap.c | 3 | ||||
| -rw-r--r-- | mm/madvise.c | 2 | ||||
| -rw-r--r-- | mm/rmap.c | 1 | ||||
| -rw-r--r-- | mm/truncate.c | 3 |
13 files changed, 78 insertions, 53 deletions
| @@ -233,16 +233,13 @@ int notify_change(struct dentry * dentry, struct iattr * attr) | |||
| 233 | return error; | 233 | return error; |
| 234 | 234 | ||
| 235 | if (ia_valid & ATTR_SIZE) | 235 | if (ia_valid & ATTR_SIZE) |
| 236 | down_write(&dentry->d_inode->i_alloc_sem); | 236 | inode_dio_wait(inode); |
| 237 | 237 | ||
| 238 | if (inode->i_op->setattr) | 238 | if (inode->i_op->setattr) |
| 239 | error = inode->i_op->setattr(dentry, attr); | 239 | error = inode->i_op->setattr(dentry, attr); |
| 240 | else | 240 | else |
| 241 | error = simple_setattr(dentry, attr); | 241 | error = simple_setattr(dentry, attr); |
| 242 | 242 | ||
| 243 | if (ia_valid & ATTR_SIZE) | ||
| 244 | up_write(&dentry->d_inode->i_alloc_sem); | ||
| 245 | |||
| 246 | if (!error) | 243 | if (!error) |
| 247 | fsnotify_change(dentry, ia_valid); | 244 | fsnotify_change(dentry, ia_valid); |
| 248 | 245 | ||
diff --git a/fs/direct-io.c b/fs/direct-io.c index 98ce3ac0d94b..354cbdbc14bd 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
| @@ -135,6 +135,50 @@ struct dio { | |||
| 135 | struct page *pages[DIO_PAGES]; /* page buffer */ | 135 | struct page *pages[DIO_PAGES]; /* page buffer */ |
| 136 | }; | 136 | }; |
| 137 | 137 | ||
| 138 | static void __inode_dio_wait(struct inode *inode) | ||
| 139 | { | ||
| 140 | wait_queue_head_t *wq = bit_waitqueue(&inode->i_state, __I_DIO_WAKEUP); | ||
| 141 | DEFINE_WAIT_BIT(q, &inode->i_state, __I_DIO_WAKEUP); | ||
| 142 | |||
| 143 | do { | ||
| 144 | prepare_to_wait(wq, &q.wait, TASK_UNINTERRUPTIBLE); | ||
| 145 | if (atomic_read(&inode->i_dio_count)) | ||
| 146 | schedule(); | ||
| 147 | } while (atomic_read(&inode->i_dio_count)); | ||
| 148 | finish_wait(wq, &q.wait); | ||
| 149 | } | ||
| 150 | |||
| 151 | /** | ||
| 152 | * inode_dio_wait - wait for outstanding DIO requests to finish | ||
| 153 | * @inode: inode to wait for | ||
| 154 | * | ||
| 155 | * Waits for all pending direct I/O requests to finish so that we can | ||
| 156 | * proceed with a truncate or equivalent operation. | ||
| 157 | * | ||
| 158 | * Must be called under a lock that serializes taking new references | ||
| 159 | * to i_dio_count, usually by inode->i_mutex. | ||
| 160 | */ | ||
| 161 | void inode_dio_wait(struct inode *inode) | ||
| 162 | { | ||
| 163 | if (atomic_read(&inode->i_dio_count)) | ||
| 164 | __inode_dio_wait(inode); | ||
| 165 | } | ||
| 166 | EXPORT_SYMBOL_GPL(inode_dio_wait); | ||
| 167 | |||
| 168 | /* | ||
| 169 | * inode_dio_done - signal finish of a direct I/O requests | ||
| 170 | * @inode: inode the direct I/O happens on | ||
| 171 | * | ||
| 172 | * This is called once we've finished processing a direct I/O request, | ||
| 173 | * and is used to wake up callers waiting for direct I/O to be quiesced. | ||
| 174 | */ | ||
| 175 | void inode_dio_done(struct inode *inode) | ||
| 176 | { | ||
| 177 | if (atomic_dec_and_test(&inode->i_dio_count)) | ||
| 178 | wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); | ||
| 179 | } | ||
| 180 | EXPORT_SYMBOL_GPL(inode_dio_done); | ||
| 181 | |||
| 138 | /* | 182 | /* |
| 139 | * How many pages are in the queue? | 183 | * How many pages are in the queue? |
| 140 | */ | 184 | */ |
| @@ -254,9 +298,7 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is | |||
| 254 | } | 298 | } |
| 255 | 299 | ||
| 256 | if (dio->flags & DIO_LOCKING) | 300 | if (dio->flags & DIO_LOCKING) |
| 257 | /* lockdep: non-owner release */ | 301 | inode_dio_done(dio->inode); |
| 258 | up_read_non_owner(&dio->inode->i_alloc_sem); | ||
| 259 | |||
| 260 | return ret; | 302 | return ret; |
| 261 | } | 303 | } |
| 262 | 304 | ||
| @@ -980,9 +1022,6 @@ out: | |||
| 980 | return ret; | 1022 | return ret; |
| 981 | } | 1023 | } |
| 982 | 1024 | ||
| 983 | /* | ||
| 984 | * Releases both i_mutex and i_alloc_sem | ||
| 985 | */ | ||
| 986 | static ssize_t | 1025 | static ssize_t |
| 987 | direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | 1026 | direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, |
| 988 | const struct iovec *iov, loff_t offset, unsigned long nr_segs, | 1027 | const struct iovec *iov, loff_t offset, unsigned long nr_segs, |
| @@ -1146,15 +1185,14 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1146 | * For writes this function is called under i_mutex and returns with | 1185 | * For writes this function is called under i_mutex and returns with |
| 1147 | * i_mutex held, for reads, i_mutex is not held on entry, but it is | 1186 | * i_mutex held, for reads, i_mutex is not held on entry, but it is |
| 1148 | * taken and dropped again before returning. | 1187 | * taken and dropped again before returning. |
| 1149 | * For reads and writes i_alloc_sem is taken in shared mode and released | 1188 | * The i_dio_count counter keeps track of the number of outstanding |
| 1150 | * on I/O completion (which may happen asynchronously after returning to | 1189 | * direct I/O requests, and truncate waits for it to reach zero. |
| 1151 | * the caller). | 1190 | * New references to i_dio_count must only be grabbed with i_mutex |
| 1191 | * held. | ||
| 1152 | * | 1192 | * |
| 1153 | * - if the flags value does NOT contain DIO_LOCKING we don't use any | 1193 | * - if the flags value does NOT contain DIO_LOCKING we don't use any |
| 1154 | * internal locking but rather rely on the filesystem to synchronize | 1194 | * internal locking but rather rely on the filesystem to synchronize |
| 1155 | * direct I/O reads/writes versus each other and truncate. | 1195 | * direct I/O reads/writes versus each other and truncate. |
| 1156 | * For reads and writes both i_mutex and i_alloc_sem are not held on | ||
| 1157 | * entry and are never taken. | ||
| 1158 | */ | 1196 | */ |
| 1159 | ssize_t | 1197 | ssize_t |
| 1160 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 1198 | __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
| @@ -1234,10 +1272,9 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
| 1234 | } | 1272 | } |
| 1235 | 1273 | ||
| 1236 | /* | 1274 | /* |
| 1237 | * Will be released at I/O completion, possibly in a | 1275 | * Will be decremented at I/O completion time. |
| 1238 | * different thread. | ||
| 1239 | */ | 1276 | */ |
| 1240 | down_read_non_owner(&inode->i_alloc_sem); | 1277 | atomic_inc(&inode->i_dio_count); |
| 1241 | } | 1278 | } |
| 1242 | 1279 | ||
| 1243 | /* | 1280 | /* |
diff --git a/fs/inode.c b/fs/inode.c index cf81baf1898a..96c77b81167c 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -168,8 +168,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode) | |||
| 168 | mutex_init(&inode->i_mutex); | 168 | mutex_init(&inode->i_mutex); |
| 169 | lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key); | 169 | lockdep_set_class(&inode->i_mutex, &sb->s_type->i_mutex_key); |
| 170 | 170 | ||
| 171 | init_rwsem(&inode->i_alloc_sem); | 171 | atomic_set(&inode->i_dio_count, 0); |
| 172 | lockdep_set_class(&inode->i_alloc_sem, &sb->s_type->i_alloc_sem_key); | ||
| 173 | 172 | ||
| 174 | mapping->a_ops = &empty_aops; | 173 | mapping->a_ops = &empty_aops; |
| 175 | mapping->host = inode; | 174 | mapping->host = inode; |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index f4b1057abdd2..b59f5ac26bef 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
| @@ -1832,9 +1832,8 @@ static ssize_t ntfs_file_buffered_write(struct kiocb *iocb, | |||
| 1832 | * fails again. | 1832 | * fails again. |
| 1833 | */ | 1833 | */ |
| 1834 | if (unlikely(NInoTruncateFailed(ni))) { | 1834 | if (unlikely(NInoTruncateFailed(ni))) { |
| 1835 | down_write(&vi->i_alloc_sem); | 1835 | inode_dio_wait(vi); |
| 1836 | err = ntfs_truncate(vi); | 1836 | err = ntfs_truncate(vi); |
| 1837 | up_write(&vi->i_alloc_sem); | ||
| 1838 | if (err || NInoTruncateFailed(ni)) { | 1837 | if (err || NInoTruncateFailed(ni)) { |
| 1839 | if (!err) | 1838 | if (!err) |
| 1840 | err = -EIO; | 1839 | err = -EIO; |
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index c05d6dcf77a4..1371487da955 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c | |||
| @@ -2357,12 +2357,7 @@ static const char *es = " Leaving inconsistent metadata. Unmount and run " | |||
| 2357 | * | 2357 | * |
| 2358 | * Returns 0 on success or -errno on error. | 2358 | * Returns 0 on success or -errno on error. |
| 2359 | * | 2359 | * |
| 2360 | * Called with ->i_mutex held. In all but one case ->i_alloc_sem is held for | 2360 | * Called with ->i_mutex held. |
| 2361 | * writing. The only case in the kernel where ->i_alloc_sem is not held is | ||
| 2362 | * mm/filemap.c::generic_file_buffered_write() where vmtruncate() is called | ||
| 2363 | * with the current i_size as the offset. The analogous place in NTFS is in | ||
| 2364 | * fs/ntfs/file.c::ntfs_file_buffered_write() where we call vmtruncate() again | ||
| 2365 | * without holding ->i_alloc_sem. | ||
| 2366 | */ | 2361 | */ |
