diff options
author | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 09:14:25 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-20 09:14:25 -0400 |
commit | b4cbb8a4e602ea77b0525d06eff89c6a6070dab3 (patch) | |
tree | a5dd723679582505ef3905c90f0c2c032d191b94 /fs/btrfs/file.c | |
parent | 526b264163068f77c5f2409031f5e25caf3900a9 (diff) | |
parent | c5d7a9230e5e277f262b6806b7f4d6b35de5a3fb (diff) |
Merge branch 'imx-features-for-arnd' of git://git.pengutronix.de/git/imx/linux-2.6 into imx/devel
Conflicts:
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mx5/devices-imx53.h
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e7872e485f13..e4e57d59edb7 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1036,11 +1036,13 @@ out: | |||
1036 | * on error we return an unlocked page and the error value | 1036 | * on error we return an unlocked page and the error value |
1037 | * on success we return a locked page and 0 | 1037 | * on success we return a locked page and 0 |
1038 | */ | 1038 | */ |
1039 | static int prepare_uptodate_page(struct page *page, u64 pos) | 1039 | static int prepare_uptodate_page(struct page *page, u64 pos, |
1040 | bool force_uptodate) | ||
1040 | { | 1041 | { |
1041 | int ret = 0; | 1042 | int ret = 0; |
1042 | 1043 | ||
1043 | if ((pos & (PAGE_CACHE_SIZE - 1)) && !PageUptodate(page)) { | 1044 | if (((pos & (PAGE_CACHE_SIZE - 1)) || force_uptodate) && |
1045 | !PageUptodate(page)) { | ||
1044 | ret = btrfs_readpage(NULL, page); | 1046 | ret = btrfs_readpage(NULL, page); |
1045 | if (ret) | 1047 | if (ret) |
1046 | return ret; | 1048 | return ret; |
@@ -1061,7 +1063,7 @@ static int prepare_uptodate_page(struct page *page, u64 pos) | |||
1061 | static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | 1063 | static noinline int prepare_pages(struct btrfs_root *root, struct file *file, |
1062 | struct page **pages, size_t num_pages, | 1064 | struct page **pages, size_t num_pages, |
1063 | loff_t pos, unsigned long first_index, | 1065 | loff_t pos, unsigned long first_index, |
1064 | size_t write_bytes) | 1066 | size_t write_bytes, bool force_uptodate) |
1065 | { | 1067 | { |
1066 | struct extent_state *cached_state = NULL; | 1068 | struct extent_state *cached_state = NULL; |
1067 | int i; | 1069 | int i; |
@@ -1075,12 +1077,6 @@ static noinline int prepare_pages(struct btrfs_root *root, struct file *file, | |||
1075 | start_pos = pos & ~((u64)root->sectorsize - 1); | 1077 | start_pos = pos & ~((u64)root->sectorsize - 1); |
1076 | last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; | 1078 | last_pos = ((u64)index + num_pages) << PAGE_CACHE_SHIFT; |
1077 | 1079 | ||
1078 | if (start_pos > inode->i_size) { | ||
1079 | err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); | ||
1080 | if (err) | ||
1081 | return err; | ||
1082 | } | ||
1083 | |||
1084 | again: | 1080 | again: |
1085 | for (i = 0; i < num_pages; i++) { | 1081 | for (i = 0; i < num_pages; i++) { |
1086 | pages[i] = find_or_create_page(inode->i_mapping, index + i, | 1082 | pages[i] = find_or_create_page(inode->i_mapping, index + i, |
@@ -1092,10 +1088,11 @@ again: | |||
1092 | } | 1088 | } |
1093 | 1089 | ||
1094 | if (i == 0) | 1090 | if (i == 0) |
1095 | err = prepare_uptodate_page(pages[i], pos); | 1091 | err = prepare_uptodate_page(pages[i], pos, |
1092 | force_uptodate); | ||
1096 | if (i == num_pages - 1) | 1093 | if (i == num_pages - 1) |
1097 | err = prepare_uptodate_page(pages[i], | 1094 | err = prepare_uptodate_page(pages[i], |
1098 | pos + write_bytes); | 1095 | pos + write_bytes, false); |
1099 | if (err) { | 1096 | if (err) { |
1100 | page_cache_release(pages[i]); | 1097 | page_cache_release(pages[i]); |
1101 | faili = i - 1; | 1098 | faili = i - 1; |
@@ -1164,6 +1161,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
1164 | size_t num_written = 0; | 1161 | size_t num_written = 0; |
1165 | int nrptrs; | 1162 | int nrptrs; |
1166 | int ret = 0; | 1163 | int ret = 0; |
1164 | bool force_page_uptodate = false; | ||
1167 | 1165 | ||
1168 | nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / | 1166 | nrptrs = min((iov_iter_count(i) + PAGE_CACHE_SIZE - 1) / |
1169 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / | 1167 | PAGE_CACHE_SIZE, PAGE_CACHE_SIZE / |
@@ -1206,7 +1204,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
1206 | * contents of pages from loop to loop | 1204 | * contents of pages from loop to loop |
1207 | */ | 1205 | */ |
1208 | ret = prepare_pages(root, file, pages, num_pages, | 1206 | ret = prepare_pages(root, file, pages, num_pages, |
1209 | pos, first_index, write_bytes); | 1207 | pos, first_index, write_bytes, |
1208 | force_page_uptodate); | ||
1210 | if (ret) { | 1209 | if (ret) { |
1211 | btrfs_delalloc_release_space(inode, | 1210 | btrfs_delalloc_release_space(inode, |
1212 | num_pages << PAGE_CACHE_SHIFT); | 1211 | num_pages << PAGE_CACHE_SHIFT); |
@@ -1223,12 +1222,15 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, | |||
1223 | if (copied < write_bytes) | 1222 | if (copied < write_bytes) |
1224 | nrptrs = 1; | 1223 | nrptrs = 1; |
1225 | 1224 | ||
1226 | if (copied == 0) | 1225 | if (copied == 0) { |
1226 | force_page_uptodate = true; | ||
1227 | dirty_pages = 0; | 1227 | dirty_pages = 0; |
1228 | else | 1228 | } else { |
1229 | force_page_uptodate = false; | ||
1229 | dirty_pages = (copied + offset + | 1230 | dirty_pages = (copied + offset + |
1230 | PAGE_CACHE_SIZE - 1) >> | 1231 | PAGE_CACHE_SIZE - 1) >> |
1231 | PAGE_CACHE_SHIFT; | 1232 | PAGE_CACHE_SHIFT; |
1233 | } | ||
1232 | 1234 | ||
1233 | /* | 1235 | /* |
1234 | * If we had a short copy we need to release the excess delaloc | 1236 | * If we had a short copy we need to release the excess delaloc |
@@ -1338,6 +1340,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1338 | struct inode *inode = fdentry(file)->d_inode; | 1340 | struct inode *inode = fdentry(file)->d_inode; |
1339 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1341 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1340 | loff_t *ppos = &iocb->ki_pos; | 1342 | loff_t *ppos = &iocb->ki_pos; |
1343 | u64 start_pos; | ||
1341 | ssize_t num_written = 0; | 1344 | ssize_t num_written = 0; |
1342 | ssize_t err = 0; | 1345 | ssize_t err = 0; |
1343 | size_t count, ocount; | 1346 | size_t count, ocount; |
@@ -1386,6 +1389,15 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb, | |||
1386 | file_update_time(file); | 1389 | file_update_time(file); |
1387 | BTRFS_I(inode)->sequence++; | 1390 | BTRFS_I(inode)->sequence++; |
1388 | 1391 | ||
1392 | start_pos = round_down(pos, root->sectorsize); | ||
1393 | if (start_pos > i_size_read(inode)) { | ||
1394 | err = btrfs_cont_expand(inode, i_size_read(inode), start_pos); | ||
1395 | if (err) { | ||
1396 | mutex_unlock(&inode->i_mutex); | ||
1397 | goto out; | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1389 | if (unlikely(file->f_flags & O_DIRECT)) { | 1401 | if (unlikely(file->f_flags & O_DIRECT)) { |
1390 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, | 1402 | num_written = __btrfs_direct_write(iocb, iov, nr_segs, |
1391 | pos, ppos, count, ocount); | 1403 | pos, ppos, count, ocount); |
@@ -1813,6 +1825,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | |||
1813 | goto out; | 1825 | goto out; |
1814 | case SEEK_DATA: | 1826 | case SEEK_DATA: |
1815 | case SEEK_HOLE: | 1827 | case SEEK_HOLE: |
1828 | if (offset >= i_size_read(inode)) { | ||
1829 | mutex_unlock(&inode->i_mutex); | ||
1830 | return -ENXIO; | ||
1831 | } | ||
1832 | |||
1816 | ret = find_desired_extent(inode, &offset, origin); | 1833 | ret = find_desired_extent(inode, &offset, origin); |
1817 | if (ret) { | 1834 | if (ret) { |
1818 | mutex_unlock(&inode->i_mutex); | 1835 | mutex_unlock(&inode->i_mutex); |
@@ -1821,11 +1838,11 @@ static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | |||
1821 | } | 1838 | } |
1822 | 1839 | ||
1823 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { | 1840 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) { |
1824 | ret = -EINVAL; | 1841 | offset = -EINVAL; |
1825 | goto out; | 1842 | goto out; |
1826 | } | 1843 | } |
1827 | if (offset > inode->i_sb->s_maxbytes) { | 1844 | if (offset > inode->i_sb->s_maxbytes) { |
1828 | ret = -EINVAL; | 1845 | offset = -EINVAL; |
1829 | goto out; | 1846 | goto out; |
1830 | } | 1847 | } |
1831 | 1848 | ||