aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/udf/inode.c86
-rw-r--r--fs/udf/super.c2
-rw-r--r--fs/udf/udf_i.h16
-rw-r--r--fs/udf/udfdecl.h5
4 files changed, 98 insertions, 11 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index cbae1ed0b7c1..7a12e48ad819 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -67,6 +67,74 @@ static void udf_update_extents(struct inode *,
67 struct extent_position *); 67 struct extent_position *);
68static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); 68static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
69 69
70static void __udf_clear_extent_cache(struct inode *inode)
71{
72 struct udf_inode_info *iinfo = UDF_I(inode);
73
74 if (iinfo->cached_extent.lstart != -1) {
75 brelse(iinfo->cached_extent.epos.bh);
76 iinfo->cached_extent.lstart = -1;
77 }
78}
79
80/* Invalidate extent cache */
81static void udf_clear_extent_cache(struct inode *inode)
82{
83 struct udf_inode_info *iinfo = UDF_I(inode);
84
85 spin_lock(&iinfo->i_extent_cache_lock);
86 __udf_clear_extent_cache(inode);
87 spin_unlock(&iinfo->i_extent_cache_lock);
88}
89
90/* Return contents of extent cache */
91static int udf_read_extent_cache(struct inode *inode, loff_t bcount,
92 loff_t *lbcount, struct extent_position *pos)
93{
94 struct udf_inode_info *iinfo = UDF_I(inode);
95 int ret = 0;
96
97 spin_lock(&iinfo->i_extent_cache_lock);
98 if ((iinfo->cached_extent.lstart <= bcount) &&
99 (iinfo->cached_extent.lstart != -1)) {
100 /* Cache hit */
101 *lbcount = iinfo->cached_extent.lstart;
102 memcpy(pos, &iinfo->cached_extent.epos,
103 sizeof(struct extent_position));
104 if (pos->bh)
105 get_bh(pos->bh);
106 ret = 1;
107 }
108 spin_unlock(&iinfo->i_extent_cache_lock);
109 return ret;
110}
111
112/* Add extent to extent cache */
113static void udf_update_extent_cache(struct inode *inode, loff_t estart,
114 struct extent_position *pos, int next_epos)
115{
116 struct udf_inode_info *iinfo = UDF_I(inode);
117
118 spin_lock(&iinfo->i_extent_cache_lock);
119 /* Invalidate previously cached extent */
120 __udf_clear_extent_cache(inode);
121 if (pos->bh)
122 get_bh(pos->bh);
123 memcpy(&iinfo->cached_extent.epos, pos,
124 sizeof(struct extent_position));
125 iinfo->cached_extent.lstart = estart;
126 if (next_epos)
127 switch (iinfo->i_alloc_type) {
128 case ICBTAG_FLAG_AD_SHORT:
129 iinfo->cached_extent.epos.offset -=
130 sizeof(struct short_ad);
131 break;
132 case ICBTAG_FLAG_AD_LONG:
133 iinfo->cached_extent.epos.offset -=
134 sizeof(struct long_ad);
135 }
136 spin_unlock(&iinfo->i_extent_cache_lock);
137}
70 138
71void udf_evict_inode(struct inode *inode) 139void udf_evict_inode(struct inode *inode)
72{ 140{
@@ -90,6 +158,7 @@ void udf_evict_inode(struct inode *inode)
90 } 158 }
91 kfree(iinfo->i_ext.i_data); 159 kfree(iinfo->i_ext.i_data);
92 iinfo->i_ext.i_data = NULL; 160 iinfo->i_ext.i_data = NULL;
161 udf_clear_extent_cache(inode);
93 if (want_delete) { 162 if (want_delete) {
94 udf_free_inode(inode); 163 udf_free_inode(inode);
95 } 164 }
@@ -105,6 +174,7 @@ static void udf_write_failed(struct address_space *mapping, loff_t to)
105 truncate_pagecache(inode, to, isize); 174 truncate_pagecache(inode, to, isize);
106 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 175 if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
107 down_write(&iinfo->i_data_sem); 176 down_write(&iinfo->i_data_sem);
177 udf_clear_extent_cache(inode);
108 udf_truncate_extents(inode); 178 udf_truncate_extents(inode);
109 up_write(&iinfo->i_data_sem); 179 up_write(&iinfo->i_data_sem);
110 } 180 }
@@ -372,7 +442,7 @@ static int udf_get_block(struct inode *inode, sector_t block,
372 iinfo->i_next_alloc_goal++; 442 iinfo->i_next_alloc_goal++;
373 } 443 }
374 444
375 445 udf_clear_extent_cache(inode);
376 phys = inode_getblk(inode, block, &err, &new); 446 phys = inode_getblk(inode, block, &err, &new);
377 if (!phys) 447 if (!phys)
378 goto abort; 448 goto abort;
@@ -1171,6 +1241,7 @@ set_size:
1171 } else { 1241 } else {
1172 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { 1242 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
1173 down_write(&iinfo->i_data_sem); 1243 down_write(&iinfo->i_data_sem);
1244 udf_clear_extent_cache(inode);
1174 memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, 1245 memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize,
1175 0x00, bsize - newsize - 1246 0x00, bsize - newsize -
1176 udf_file_entry_alloc_offset(inode)); 1247 udf_file_entry_alloc_offset(inode));
@@ -1184,6 +1255,7 @@ set_size:
1184 if (err) 1255 if (err)
1185 return err; 1256 return err;
1186 down_write(&iinfo->i_data_sem); 1257 down_write(&iinfo->i_data_sem);
1258 udf_clear_extent_cache(inode);
1187 truncate_setsize(inode, newsize); 1259 truncate_setsize(inode, newsize);
1188 udf_truncate_extents(inode); 1260 udf_truncate_extents(inode);
1189 up_write(&iinfo->i_data_sem); 1261 up_write(&iinfo->i_data_sem);
@@ -2156,11 +2228,12 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
2156 struct udf_inode_info *iinfo; 2228 struct udf_inode_info *iinfo;
2157 2229
2158 iinfo = UDF_I(inode); 2230 iinfo = UDF_I(inode);
2159 pos->offset = 0; 2231 if (!udf_read_extent_cache(inode, bcount, &lbcount, pos)) {
2160 pos->block = iinfo->i_location; 2232 pos->offset = 0;
2161 pos->bh = NULL; 2233 pos->block = iinfo->i_location;
2234 pos->bh = NULL;
2235 }
2162 *elen = 0; 2236 *elen = 0;
2163
2164 do { 2237 do {
2165 etype = udf_next_aext(inode, pos, eloc, elen, 1); 2238 etype = udf_next_aext(inode, pos, eloc, elen, 1);
2166 if (etype == -1) { 2239 if (etype == -1) {
@@ -2170,7 +2243,8 @@ int8_t inode_bmap(struct inode *inode, sector_t block,
2170 } 2243 }
2171 lbcount += *elen; 2244 lbcount += *elen;
2172 } while (lbcount <= bcount); 2245 } while (lbcount <= bcount);
2173 2246 /* update extent cache */
2247 udf_update_extent_cache(inode, lbcount - *elen, pos, 1);
2174 *offset = (bcount + *elen - lbcount) >> blocksize_bits; 2248 *offset = (bcount + *elen - lbcount) >> blocksize_bits;
2175 2249
2176 return etype; 2250 return etype;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 186adbf94b20..da8ce9f14387 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -134,6 +134,8 @@ static struct inode *udf_alloc_inode(struct super_block *sb)
134 ei->i_next_alloc_goal = 0; 134 ei->i_next_alloc_goal = 0;
135 ei->i_strat4096 = 0; 135 ei->i_strat4096 = 0;
136 init_rwsem(&ei->i_data_sem); 136 init_rwsem(&ei->i_data_sem);
137 ei->cached_extent.lstart = -1;
138 spin_lock_init(&ei->i_extent_cache_lock);
137 139
138 return &ei->vfs_inode; 140 return &ei->vfs_inode;
139} 141}
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
index bb8309dcd5c1..b5cd8ed2aa12 100644
--- a/fs/udf/udf_i.h
+++ b/fs/udf/udf_i.h
@@ -1,6 +1,19 @@
1#ifndef _UDF_I_H 1#ifndef _UDF_I_H
2#define _UDF_I_H 2#define _UDF_I_H
3 3
4struct extent_position {
5 struct buffer_head *bh;
6 uint32_t offset;
7 struct kernel_lb_addr block;
8};
9
10struct udf_ext_cache {
11 /* Extent position */
12 struct extent_position epos;
13 /* Start logical offset in bytes */
14 loff_t lstart;
15};
16
4/* 17/*
5 * The i_data_sem and i_mutex serve for protection of allocation information 18 * The i_data_sem and i_mutex serve for protection of allocation information
6 * of a regular files and symlinks. This includes all extents belonging to 19 * of a regular files and symlinks. This includes all extents belonging to
@@ -35,6 +48,9 @@ struct udf_inode_info {
35 __u8 *i_data; 48 __u8 *i_data;
36 } i_ext; 49 } i_ext;
37 struct rw_semaphore i_data_sem; 50 struct rw_semaphore i_data_sem;
51 struct udf_ext_cache cached_extent;
52 /* Spinlock for protecting extent cache */
53 spinlock_t i_extent_cache_lock;
38 struct inode vfs_inode; 54 struct inode vfs_inode;
39}; 55};
40 56
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index de038da6f6bd..be7dabbbcb49 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -113,11 +113,6 @@ struct ustr {
113 uint8_t u_len; 113 uint8_t u_len;
114}; 114};
115 115
116struct extent_position {
117 struct buffer_head *bh;
118 uint32_t offset;
119 struct kernel_lb_addr block;
120};
121 116
122/* super.c */ 117/* super.c */
123 118