Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/fs/affs/file.c (Version 2.6.25) and /linux/fs/affs/file.c (Version 2.6.31.13)


  1 /*                                                  1 /*
  2  *  linux/fs/affs/file.c                            2  *  linux/fs/affs/file.c
  3  *                                                  3  *
  4  *  (c) 1996  Hans-Joachim Widmaier - Rewritte      4  *  (c) 1996  Hans-Joachim Widmaier - Rewritten
  5  *                                                  5  *
  6  *  (C) 1993  Ray Burr - Modified for Amiga FF      6  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  7  *                                                  7  *
  8  *  (C) 1992  Eric Youngdale Modified for ISO       8  *  (C) 1992  Eric Youngdale Modified for ISO 9660 filesystem.
  9  *                                                  9  *
 10  *  (C) 1991  Linus Torvalds - minix filesyste     10  *  (C) 1991  Linus Torvalds - minix filesystem
 11  *                                                 11  *
 12  *  affs regular file handling primitives          12  *  affs regular file handling primitives
 13  */                                                13  */
 14                                                    14 
 15 #include "affs.h"                                  15 #include "affs.h"
 16                                                    16 
 17 #if PAGE_SIZE < 4096                               17 #if PAGE_SIZE < 4096
 18 #error PAGE_SIZE must be at least 4096             18 #error PAGE_SIZE must be at least 4096
 19 #endif                                             19 #endif
 20                                                    20 
 21 static int affs_grow_extcache(struct inode *in     21 static int affs_grow_extcache(struct inode *inode, u32 lc_idx);
 22 static struct buffer_head *affs_alloc_extblock     22 static struct buffer_head *affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext);
 23 static inline struct buffer_head *affs_get_ext     23 static inline struct buffer_head *affs_get_extblock(struct inode *inode, u32 ext);
 24 static struct buffer_head *affs_get_extblock_s     24 static struct buffer_head *affs_get_extblock_slow(struct inode *inode, u32 ext);
 25 static int affs_file_open(struct inode *inode,     25 static int affs_file_open(struct inode *inode, struct file *filp);
 26 static int affs_file_release(struct inode *ino     26 static int affs_file_release(struct inode *inode, struct file *filp);
 27                                                    27 
 28 const struct file_operations affs_file_operati     28 const struct file_operations affs_file_operations = {
 29         .llseek         = generic_file_llseek,     29         .llseek         = generic_file_llseek,
 30         .read           = do_sync_read,            30         .read           = do_sync_read,
 31         .aio_read       = generic_file_aio_rea     31         .aio_read       = generic_file_aio_read,
 32         .write          = do_sync_write,           32         .write          = do_sync_write,
 33         .aio_write      = generic_file_aio_wri     33         .aio_write      = generic_file_aio_write,
 34         .mmap           = generic_file_mmap,       34         .mmap           = generic_file_mmap,
 35         .open           = affs_file_open,          35         .open           = affs_file_open,
 36         .release        = affs_file_release,       36         .release        = affs_file_release,
 37         .fsync          = file_fsync,          !!  37         .fsync          = affs_file_fsync,
 38         .splice_read    = generic_file_splice_     38         .splice_read    = generic_file_splice_read,
 39 };                                                 39 };
 40                                                    40 
 41 const struct inode_operations affs_file_inode_     41 const struct inode_operations affs_file_inode_operations = {
 42         .truncate       = affs_truncate,           42         .truncate       = affs_truncate,
 43         .setattr        = affs_notify_change,      43         .setattr        = affs_notify_change,
 44 };                                                 44 };
 45                                                    45 
 46 static int                                         46 static int
 47 affs_file_open(struct inode *inode, struct fil     47 affs_file_open(struct inode *inode, struct file *filp)
 48 {                                                  48 {
 49         if (atomic_read(&filp->f_count) != 1)  !!  49         pr_debug("AFFS: open(%lu,%d)\n",
 50                 return 0;                      !!  50                  inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
 51         pr_debug("AFFS: open(%d)\n", AFFS_I(in !!  51         atomic_inc(&AFFS_I(inode)->i_opencnt);
 52         AFFS_I(inode)->i_opencnt++;            << 
 53         return 0;                                  52         return 0;
 54 }                                                  53 }
 55                                                    54 
 56 static int                                         55 static int
 57 affs_file_release(struct inode *inode, struct      56 affs_file_release(struct inode *inode, struct file *filp)
 58 {                                                  57 {
 59         if (atomic_read(&filp->f_count) != 0)  !!  58         pr_debug("AFFS: release(%lu, %d)\n",
 60                 return 0;                      !!  59                  inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt));
 61         pr_debug("AFFS: release(%d)\n", AFFS_I !!  60 
 62         AFFS_I(inode)->i_opencnt--;            !!  61         if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) {
 63         if (!AFFS_I(inode)->i_opencnt)         !!  62                 mutex_lock(&inode->i_mutex);
                                                   >>  63                 if (inode->i_size != AFFS_I(inode)->mmu_private)
                                                   >>  64                         affs_truncate(inode);
 64                 affs_free_prealloc(inode);         65                 affs_free_prealloc(inode);
                                                   >>  66                 mutex_unlock(&inode->i_mutex);
                                                   >>  67         }
 65                                                    68 
 66         return 0;                                  69         return 0;
 67 }                                                  70 }
 68                                                    71 
 69 static int                                         72 static int
 70 affs_grow_extcache(struct inode *inode, u32 lc     73 affs_grow_extcache(struct inode *inode, u32 lc_idx)
 71 {                                                  74 {
 72         struct super_block      *sb = inode->i     75         struct super_block      *sb = inode->i_sb;
 73         struct buffer_head      *bh;               76         struct buffer_head      *bh;
 74         u32 lc_max;                                77         u32 lc_max;
 75         int i, j, key;                             78         int i, j, key;
 76                                                    79 
 77         if (!AFFS_I(inode)->i_lc) {                80         if (!AFFS_I(inode)->i_lc) {
 78                 char *ptr = (char *)get_zeroed     81                 char *ptr = (char *)get_zeroed_page(GFP_NOFS);
 79                 if (!ptr)                          82                 if (!ptr)
 80                         return -ENOMEM;            83                         return -ENOMEM;
 81                 AFFS_I(inode)->i_lc = (u32 *)p     84                 AFFS_I(inode)->i_lc = (u32 *)ptr;
 82                 AFFS_I(inode)->i_ac = (struct      85                 AFFS_I(inode)->i_ac = (struct affs_ext_key *)(ptr + AFFS_CACHE_SIZE / 2);
 83         }                                          86         }
 84                                                    87 
 85         lc_max = AFFS_LC_SIZE << AFFS_I(inode)     88         lc_max = AFFS_LC_SIZE << AFFS_I(inode)->i_lc_shift;
 86                                                    89 
 87         if (AFFS_I(inode)->i_extcnt > lc_max)      90         if (AFFS_I(inode)->i_extcnt > lc_max) {
 88                 u32 lc_shift, lc_mask, tmp, of     91                 u32 lc_shift, lc_mask, tmp, off;
 89                                                    92 
 90                 /* need to recalculate linear      93                 /* need to recalculate linear cache, start from old size */
 91                 lc_shift = AFFS_I(inode)->i_lc     94                 lc_shift = AFFS_I(inode)->i_lc_shift;
 92                 tmp = (AFFS_I(inode)->i_extcnt     95                 tmp = (AFFS_I(inode)->i_extcnt / AFFS_LC_SIZE) >> lc_shift;
 93                 for (; tmp; tmp >>= 1)             96                 for (; tmp; tmp >>= 1)
 94                         lc_shift++;                97                         lc_shift++;
 95                 lc_mask = (1 << lc_shift) - 1;     98                 lc_mask = (1 << lc_shift) - 1;
 96                                                    99 
 97                 /* fix idx and old size to new    100                 /* fix idx and old size to new shift */
 98                 lc_idx >>= (lc_shift - AFFS_I(    101                 lc_idx >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
 99                 AFFS_I(inode)->i_lc_size >>= (    102                 AFFS_I(inode)->i_lc_size >>= (lc_shift - AFFS_I(inode)->i_lc_shift);
100                                                   103 
101                 /* first shrink old cache to m    104                 /* first shrink old cache to make more space */
102                 off = 1 << (lc_shift - AFFS_I(    105                 off = 1 << (lc_shift - AFFS_I(inode)->i_lc_shift);
103                 for (i = 1, j = off; j < AFFS_    106                 for (i = 1, j = off; j < AFFS_LC_SIZE; i++, j += off)
104                         AFFS_I(inode)->i_ac[i]    107                         AFFS_I(inode)->i_ac[i] = AFFS_I(inode)->i_ac[j];
105                                                   108 
106                 AFFS_I(inode)->i_lc_shift = lc    109                 AFFS_I(inode)->i_lc_shift = lc_shift;
107                 AFFS_I(inode)->i_lc_mask = lc_    110                 AFFS_I(inode)->i_lc_mask = lc_mask;
108         }                                         111         }
109                                                   112 
110         /* fill cache to the needed index */      113         /* fill cache to the needed index */
111         i = AFFS_I(inode)->i_lc_size;             114         i = AFFS_I(inode)->i_lc_size;
112         AFFS_I(inode)->i_lc_size = lc_idx + 1;    115         AFFS_I(inode)->i_lc_size = lc_idx + 1;
113         for (; i <= lc_idx; i++) {                116         for (; i <= lc_idx; i++) {
114                 if (!i) {                         117                 if (!i) {
115                         AFFS_I(inode)->i_lc[0]    118                         AFFS_I(inode)->i_lc[0] = inode->i_ino;
116                         continue;                 119                         continue;
117                 }                                 120                 }
118                 key = AFFS_I(inode)->i_lc[i -     121                 key = AFFS_I(inode)->i_lc[i - 1];
119                 j = AFFS_I(inode)->i_lc_mask +    122                 j = AFFS_I(inode)->i_lc_mask + 1;
120                 // unlock cache                   123                 // unlock cache
121                 for (; j > 0; j--) {              124                 for (; j > 0; j--) {
122                         bh = affs_bread(sb, ke    125                         bh = affs_bread(sb, key);
123                         if (!bh)                  126                         if (!bh)
124                                 goto err;         127                                 goto err;
125                         key = be32_to_cpu(AFFS    128                         key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
126                         affs_brelse(bh);          129                         affs_brelse(bh);
127                 }                                 130                 }
128                 // lock cache                     131                 // lock cache
129                 AFFS_I(inode)->i_lc[i] = key;     132                 AFFS_I(inode)->i_lc[i] = key;
130         }                                         133         }
131                                                   134 
132         return 0;                                 135         return 0;
133                                                   136 
134 err:                                              137 err:
135         // lock cache                             138         // lock cache
136         return -EIO;                              139         return -EIO;
137 }                                                 140 }
138                                                   141 
139 static struct buffer_head *                       142 static struct buffer_head *
140 affs_alloc_extblock(struct inode *inode, struc    143 affs_alloc_extblock(struct inode *inode, struct buffer_head *bh, u32 ext)
141 {                                                 144 {
142         struct super_block *sb = inode->i_sb;     145         struct super_block *sb = inode->i_sb;
143         struct buffer_head *new_bh;               146         struct buffer_head *new_bh;
144         u32 blocknr, tmp;                         147         u32 blocknr, tmp;
145                                                   148 
146         blocknr = affs_alloc_block(inode, bh->    149         blocknr = affs_alloc_block(inode, bh->b_blocknr);
147         if (!blocknr)                             150         if (!blocknr)
148                 return ERR_PTR(-ENOSPC);          151                 return ERR_PTR(-ENOSPC);
149                                                   152 
150         new_bh = affs_getzeroblk(sb, blocknr);    153         new_bh = affs_getzeroblk(sb, blocknr);
151         if (!new_bh) {                            154         if (!new_bh) {
152                 affs_free_block(sb, blocknr);     155                 affs_free_block(sb, blocknr);
153                 return ERR_PTR(-EIO);             156                 return ERR_PTR(-EIO);
154         }                                         157         }
155                                                   158 
156         AFFS_HEAD(new_bh)->ptype = cpu_to_be32    159         AFFS_HEAD(new_bh)->ptype = cpu_to_be32(T_LIST);
157         AFFS_HEAD(new_bh)->key = cpu_to_be32(b    160         AFFS_HEAD(new_bh)->key = cpu_to_be32(blocknr);
158         AFFS_TAIL(sb, new_bh)->stype = cpu_to_    161         AFFS_TAIL(sb, new_bh)->stype = cpu_to_be32(ST_FILE);
159         AFFS_TAIL(sb, new_bh)->parent = cpu_to    162         AFFS_TAIL(sb, new_bh)->parent = cpu_to_be32(inode->i_ino);
160         affs_fix_checksum(sb, new_bh);            163         affs_fix_checksum(sb, new_bh);
161                                                   164 
162         mark_buffer_dirty_inode(new_bh, inode)    165         mark_buffer_dirty_inode(new_bh, inode);
163                                                   166 
164         tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->e    167         tmp = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
165         if (tmp)                                  168         if (tmp)
166                 affs_warning(sb, "alloc_ext",     169                 affs_warning(sb, "alloc_ext", "previous extension set (%x)", tmp);
167         AFFS_TAIL(sb, bh)->extension = cpu_to_    170         AFFS_TAIL(sb, bh)->extension = cpu_to_be32(blocknr);
168         affs_adjust_checksum(bh, blocknr - tmp    171         affs_adjust_checksum(bh, blocknr - tmp);
169         mark_buffer_dirty_inode(bh, inode);       172         mark_buffer_dirty_inode(bh, inode);
170                                                   173 
171         AFFS_I(inode)->i_extcnt++;                174         AFFS_I(inode)->i_extcnt++;
172         mark_inode_dirty(inode);                  175         mark_inode_dirty(inode);
173                                                   176 
174         return new_bh;                            177         return new_bh;
175 }                                                 178 }
176                                                   179 
177 static inline struct buffer_head *                180 static inline struct buffer_head *
178 affs_get_extblock(struct inode *inode, u32 ext    181 affs_get_extblock(struct inode *inode, u32 ext)
179 {                                                 182 {
180         /* inline the simplest case: same exte    183         /* inline the simplest case: same extended block as last time */
181         struct buffer_head *bh = AFFS_I(inode)    184         struct buffer_head *bh = AFFS_I(inode)->i_ext_bh;
182         if (ext == AFFS_I(inode)->i_ext_last)     185         if (ext == AFFS_I(inode)->i_ext_last)
183                 atomic_inc(&bh->b_count);      !! 186                 get_bh(bh);
184         else                                      187         else
185                 /* we have to do more (not inl    188                 /* we have to do more (not inlined) */
186                 bh = affs_get_extblock_slow(in    189                 bh = affs_get_extblock_slow(inode, ext);
187                                                   190 
188         return bh;                                191         return bh;
189 }                                                 192 }
190                                                   193 
191 static struct buffer_head *                       194 static struct buffer_head *
192 affs_get_extblock_slow(struct inode *inode, u3    195 affs_get_extblock_slow(struct inode *inode, u32 ext)
193 {                                                 196 {
194         struct super_block *sb = inode->i_sb;     197         struct super_block *sb = inode->i_sb;
195         struct buffer_head *bh;                   198         struct buffer_head *bh;
196         u32 ext_key;                              199         u32 ext_key;
197         u32 lc_idx, lc_off, ac_idx;               200         u32 lc_idx, lc_off, ac_idx;
198         u32 tmp, idx;                             201         u32 tmp, idx;
199                                                   202 
200         if (ext == AFFS_I(inode)->i_ext_last +    203         if (ext == AFFS_I(inode)->i_ext_last + 1) {
201                 /* read the next extended bloc    204                 /* read the next extended block from the current one */
202                 bh = AFFS_I(inode)->i_ext_bh;     205                 bh = AFFS_I(inode)->i_ext_bh;
203                 ext_key = be32_to_cpu(AFFS_TAI    206                 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
204                 if (ext < AFFS_I(inode)->i_ext    207                 if (ext < AFFS_I(inode)->i_extcnt)
205                         goto read_ext;            208                         goto read_ext;
206                 if (ext > AFFS_I(inode)->i_ext    209                 if (ext > AFFS_I(inode)->i_extcnt)
207                         BUG();                    210                         BUG();
208                 bh = affs_alloc_extblock(inode    211                 bh = affs_alloc_extblock(inode, bh, ext);
209                 if (IS_ERR(bh))                   212                 if (IS_ERR(bh))
210                         return bh;                213                         return bh;
211                 goto store_ext;                   214                 goto store_ext;
212         }                                         215         }
213                                                   216 
214         if (ext == 0) {                           217         if (ext == 0) {
215                 /* we seek back to the file he    218                 /* we seek back to the file header block */
216                 ext_key = inode->i_ino;           219                 ext_key = inode->i_ino;
217                 goto read_ext;                    220                 goto read_ext;
218         }                                         221         }
219                                                   222 
220         if (ext >= AFFS_I(inode)->i_extcnt) {     223         if (ext >= AFFS_I(inode)->i_extcnt) {
221                 struct buffer_head *prev_bh;      224                 struct buffer_head *prev_bh;
222                                                   225 
223                 /* allocate a new extended blo    226                 /* allocate a new extended block */
224                 if (ext > AFFS_I(inode)->i_ext    227                 if (ext > AFFS_I(inode)->i_extcnt)
225                         BUG();                    228                         BUG();
226                                                   229 
227                 /* get previous extended block    230                 /* get previous extended block */
228                 prev_bh = affs_get_extblock(in    231                 prev_bh = affs_get_extblock(inode, ext - 1);
229                 if (IS_ERR(prev_bh))              232                 if (IS_ERR(prev_bh))
230                         return prev_bh;           233                         return prev_bh;
231                 bh = affs_alloc_extblock(inode    234                 bh = affs_alloc_extblock(inode, prev_bh, ext);
232                 affs_brelse(prev_bh);             235                 affs_brelse(prev_bh);
233                 if (IS_ERR(bh))                   236                 if (IS_ERR(bh))
234                         return bh;                237                         return bh;
235                 goto store_ext;                   238                 goto store_ext;
236         }                                         239         }
237                                                   240 
238 again:                                            241 again:
239         /* check if there is an extended cache    242         /* check if there is an extended cache and whether it's large enough */
240         lc_idx = ext >> AFFS_I(inode)->i_lc_sh    243         lc_idx = ext >> AFFS_I(inode)->i_lc_shift;
241         lc_off = ext & AFFS_I(inode)->i_lc_mas    244         lc_off = ext & AFFS_I(inode)->i_lc_mask;
242                                                   245 
243         if (lc_idx >= AFFS_I(inode)->i_lc_size    246         if (lc_idx >= AFFS_I(inode)->i_lc_size) {
244                 int err;                          247                 int err;
245                                                   248 
246                 err = affs_grow_extcache(inode    249                 err = affs_grow_extcache(inode, lc_idx);
247                 if (err)                          250                 if (err)
248                         return ERR_PTR(err);      251                         return ERR_PTR(err);
249                 goto again;                       252                 goto again;
250         }                                         253         }
251                                                   254 
252         /* every n'th key we find in the linea    255         /* every n'th key we find in the linear cache */
253         if (!lc_off) {                            256         if (!lc_off) {
254                 ext_key = AFFS_I(inode)->i_lc[    257                 ext_key = AFFS_I(inode)->i_lc[lc_idx];
255                 goto read_ext;                    258                 goto read_ext;
256         }                                         259         }
257                                                   260 
258         /* maybe it's still in the associative    261         /* maybe it's still in the associative cache */
259         ac_idx = (ext - lc_idx - 1) & AFFS_AC_    262         ac_idx = (ext - lc_idx - 1) & AFFS_AC_MASK;
260         if (AFFS_I(inode)->i_ac[ac_idx].ext ==    263         if (AFFS_I(inode)->i_ac[ac_idx].ext == ext) {
261                 ext_key = AFFS_I(inode)->i_ac[    264                 ext_key = AFFS_I(inode)->i_ac[ac_idx].key;
262                 goto read_ext;                    265                 goto read_ext;
263         }                                         266         }
264                                                   267 
265         /* try to find one of the previous ext    268         /* try to find one of the previous extended blocks */
266         tmp = ext;                                269         tmp = ext;
267         idx = ac_idx;                             270         idx = ac_idx;
268         while (--tmp, --lc_off > 0) {             271         while (--tmp, --lc_off > 0) {
269                 idx = (idx - 1) & AFFS_AC_MASK    272                 idx = (idx - 1) & AFFS_AC_MASK;
270                 if (AFFS_I(inode)->i_ac[idx].e    273                 if (AFFS_I(inode)->i_ac[idx].ext == tmp) {
271                         ext_key = AFFS_I(inode    274                         ext_key = AFFS_I(inode)->i_ac[idx].key;
272                         goto find_ext;            275                         goto find_ext;
273                 }                                 276                 }
274         }                                         277         }
275                                                   278 
276         /* fall back to the linear cache */       279         /* fall back to the linear cache */
277         ext_key = AFFS_I(inode)->i_lc[lc_idx];    280         ext_key = AFFS_I(inode)->i_lc[lc_idx];
278 find_ext:                                         281 find_ext:
279         /* read all extended blocks until we f    282         /* read all extended blocks until we find the one we need */
280         //unlock cache                            283         //unlock cache
281         do {                                      284         do {
282                 bh = affs_bread(sb, ext_key);     285                 bh = affs_bread(sb, ext_key);
283                 if (!bh)                          286                 if (!bh)
284                         goto err_bread;           287                         goto err_bread;
285                 ext_key = be32_to_cpu(AFFS_TAI    288                 ext_key = be32_to_cpu(AFFS_TAIL(sb, bh)->extension);
286                 affs_brelse(bh);                  289                 affs_brelse(bh);
287                 tmp++;                            290                 tmp++;
288         } while (tmp < ext);                      291         } while (tmp < ext);
289         //lock cache                              292         //lock cache
290                                                   293 
291         /* store it in the associative cache *    294         /* store it in the associative cache */
292         // recalculate ac_idx?                    295         // recalculate ac_idx?
293         AFFS_I(inode)->i_ac[ac_idx].ext = ext;    296         AFFS_I(inode)->i_ac[ac_idx].ext = ext;
294         AFFS_I(inode)->i_ac[ac_idx].key = ext_    297         AFFS_I(inode)->i_ac[ac_idx].key = ext_key;
295                                                   298 
296 read_ext:                                         299 read_ext:
297         /* finally read the right extended blo    300         /* finally read the right extended block */
298         //unlock cache                            301         //unlock cache
299         bh = affs_bread(sb, ext_key);             302         bh = affs_bread(sb, ext_key);
300         if (!bh)                                  303         if (!bh)
301                 goto err_bread;                   304                 goto err_bread;
302         //lock cache                              305         //lock cache
303                                                   306 
304 store_ext:                                        307 store_ext:
305         /* release old cached extended block a    308         /* release old cached extended block and store the new one */
306         affs_brelse(AFFS_I(inode)->i_ext_bh);     309         affs_brelse(AFFS_I(inode)->i_ext_bh);
307         AFFS_I(inode)->i_ext_last = ext;          310         AFFS_I(inode)->i_ext_last = ext;
308         AFFS_I(inode)->i_ext_bh = bh;             311         AFFS_I(inode)->i_ext_bh = bh;
309         atomic_inc(&bh->b_count);              !! 312         get_bh(bh);
310                                                   313 
311         return bh;                                314         return bh;
312                                                   315 
313 err_bread:                                        316 err_bread:
314         affs_brelse(bh);                          317         affs_brelse(bh);
315         return ERR_PTR(-EIO);                     318         return ERR_PTR(-EIO);
316 }                                                 319 }
317                                                   320 
318 static int                                        321 static int
319 affs_get_block(struct inode *inode, sector_t b    322 affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
320 {                                                 323 {
321         struct super_block      *sb = inode->i    324         struct super_block      *sb = inode->i_sb;
322         struct buffer_head      *ext_bh;          325         struct buffer_head      *ext_bh;
323         u32                      ext;             326         u32                      ext;
324                                                   327 
325         pr_debug("AFFS: get_block(%u, %lu)\n",    328         pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block);
326                                                   329 
327                                                !! 330         BUG_ON(block > (sector_t)0x7fffffffUL);
328         if (block > (sector_t)0x7fffffffUL)    << 
329                 BUG();                         << 
330                                                   331 
331         if (block >= AFFS_I(inode)->i_blkcnt)     332         if (block >= AFFS_I(inode)->i_blkcnt) {
332                 if (block > AFFS_I(inode)->i_b    333                 if (block > AFFS_I(inode)->i_blkcnt || !create)
333                         goto err_big;             334                         goto err_big;
334         } else                                    335         } else
335                 create = 0;                       336                 create = 0;
336                                                   337 
337         //lock cache                              338         //lock cache
338         affs_lock_ext(inode);                     339         affs_lock_ext(inode);
339                                                   340 
340         ext = (u32)block / AFFS_SB(sb)->s_hash    341         ext = (u32)block / AFFS_SB(sb)->s_hashsize;
341         block -= ext * AFFS_SB(sb)->s_hashsize    342         block -= ext * AFFS_SB(sb)->s_hashsize;
342         ext_bh = affs_get_extblock(inode, ext)    343         ext_bh = affs_get_extblock(inode, ext);
343         if (IS_ERR(ext_bh))                       344         if (IS_ERR(ext_bh))
344                 goto err_ext;                     345                 goto err_ext;
345         map_bh(bh_result, sb, (sector_t)be32_t    346         map_bh(bh_result, sb, (sector_t)be32_to_cpu(AFFS_BLOCK(sb, ext_bh, block)));
346                                                   347 
347         if (create) {                             348         if (create) {
348                 u32 blocknr = affs_alloc_block    349                 u32 blocknr = affs_alloc_block(inode, ext_bh->b_blocknr);
349                 if (!blocknr)                     350                 if (!blocknr)
350                         goto err_alloc;           351                         goto err_alloc;
351                 set_buffer_new(bh_result);        352                 set_buffer_new(bh_result);
352                 AFFS_I(inode)->mmu_private +=     353                 AFFS_I(inode)->mmu_private += AFFS_SB(sb)->s_data_blksize;
353                 AFFS_I(inode)->i_blkcnt++;        354                 AFFS_I(inode)->i_blkcnt++;
354                                                   355 
355                 /* store new block */             356                 /* store new block */
356                 if (bh_result->b_blocknr)         357                 if (bh_result->b_blocknr)
357                         affs_warning(sb, "get_    358                         affs_warning(sb, "get_block", "block already set (%x)", bh_result->b_blocknr);
358                 AFFS_BLOCK(sb, ext_bh, block)     359                 AFFS_BLOCK(sb, ext_bh, block) = cpu_to_be32(blocknr);
359                 AFFS_HEAD(ext_bh)->block_count    360                 AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(block + 1);
360                 affs_adjust_checksum(ext_bh, b    361                 affs_adjust_checksum(ext_bh, blocknr - bh_result->b_blocknr + 1);
361                 bh_result->b_blocknr = blocknr    362                 bh_result->b_blocknr = blocknr;
362                                                   363 
363                 if (!block) {                     364                 if (!block) {
364                         /* insert first block     365                         /* insert first block into header block */
365                         u32 tmp = be32_to_cpu(    366                         u32 tmp = be32_to_cpu(AFFS_HEAD(ext_bh)->first_data);
366                         if (tmp)                  367                         if (tmp)
367                                 affs_warning(s    368                                 affs_warning(sb, "get_block", "first block already set (%d)", tmp);
368                         AFFS_HEAD(ext_bh)->fir    369                         AFFS_HEAD(ext_bh)->first_data = cpu_to_be32(blocknr);
369                         affs_adjust_checksum(e    370                         affs_adjust_checksum(ext_bh, blocknr - tmp);
370                 }                                 371                 }
371         }                                         372         }
372                                                   373 
373         affs_brelse(ext_bh);                      374         affs_brelse(ext_bh);
374         //unlock cache                            375         //unlock cache
375         affs_unlock_ext(inode);                   376         affs_unlock_ext(inode);
376         return 0;                                 377         return 0;
377                                                   378 
378 err_big:                                          379 err_big:
379         affs_error(inode->i_sb,"get_block","st    380         affs_error(inode->i_sb,"get_block","strange block request %d", block);
380         return -EIO;                              381         return -EIO;
381 err_ext:                                          382 err_ext:
382         // unlock cache                           383         // unlock cache
383         affs_unlock_ext(inode);                   384         affs_unlock_ext(inode);
384         return PTR_ERR(ext_bh);                   385         return PTR_ERR(ext_bh);
385 err_alloc:                                        386 err_alloc:
386         brelse(ext_bh);                           387         brelse(ext_bh);
387         clear_buffer_mapped(bh_result);           388         clear_buffer_mapped(bh_result);
388         bh_result->b_bdev = NULL;                 389         bh_result->b_bdev = NULL;
389         // unlock cache                           390         // unlock cache
390         affs_unlock_ext(inode);                   391         affs_unlock_ext(inode);
391         return -ENOSPC;                           392         return -ENOSPC;
392 }                                                 393 }
393                                                   394 
394 static int affs_writepage(struct page *page, s    395 static int affs_writepage(struct page *page, struct writeback_control *wbc)
395 {                                                 396 {
396         return block_write_full_page(page, aff    397         return block_write_full_page(page, affs_get_block, wbc);
397 }                                                 398 }
398                                                   399 
399 static int affs_readpage(struct file *file, st    400 static int affs_readpage(struct file *file, struct page *page)
400 {                                                 401 {
401         return block_read_full_page(page, affs    402         return block_read_full_page(page, affs_get_block);
402 }                                                 403 }
403                                                   404 
404 static int affs_write_begin(struct file *file,    405 static int affs_write_begin(struct file *file, struct address_space *mapping,
405                         loff_t pos, unsigned l    406                         loff_t pos, unsigned len, unsigned flags,
406                         struct page **pagep, v    407                         struct page **pagep, void **fsdata)
407 {                                                 408 {
408         *pagep = NULL;                            409         *pagep = NULL;
409         return cont_write_begin(file, mapping,    410         return cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
410                                 affs_get_block    411                                 affs_get_block,
411                                 &AFFS_I(mappin    412                                 &AFFS_I(mapping->host)->mmu_private);
412 }                                                 413 }
413                                                   414 
414 static sector_t _affs_bmap(struct address_spac    415 static sector_t _affs_bmap(struct address_space *mapping, sector_t block)
415 {                                                 416 {
416         return generic_block_bmap(mapping,bloc    417         return generic_block_bmap(mapping,block,affs_get_block);
417 }                                                 418 }
418                                                   419 
419 const struct address_space_operations affs_aop    420 const struct address_space_operations affs_aops = {
420         .readpage = affs_readpage,                421         .readpage = affs_readpage,
421         .writepage = affs_writepage,              422         .writepage = affs_writepage,
422         .sync_page = block_sync_page,             423         .sync_page = block_sync_page,
423         .write_begin = affs_write_begin,          424         .write_begin = affs_write_begin,
424         .write_end = generic_write_end,           425         .write_end = generic_write_end,
425         .bmap = _affs_bmap                        426         .bmap = _affs_bmap
426 };                                                427 };
427                                                   428 
428 static inline struct buffer_head *                429 static inline struct buffer_head *
429 affs_bread_ino(struct inode *inode, int block,    430 affs_bread_ino(struct inode *inode, int block, int create)
430 {                                                 431 {
431         struct buffer_head *bh, tmp_bh;           432         struct buffer_head *bh, tmp_bh;
432         int err;                                  433         int err;
433                                                   434 
434         tmp_bh.b_state = 0;                       435         tmp_bh.b_state = 0;
435         err = affs_get_block(inode, block, &tm    436         err = affs_get_block(inode, block, &tmp_bh, create);
436         if (!err) {                               437         if (!err) {
437                 bh = affs_bread(inode->i_sb, t    438                 bh = affs_bread(inode->i_sb, tmp_bh.b_blocknr);
438                 if (bh) {                         439                 if (bh) {
439                         bh->b_state |= tmp_bh.    440                         bh->b_state |= tmp_bh.b_state;
440                         return bh;                441                         return bh;
441                 }                                 442                 }
442                 err = -EIO;                       443                 err = -EIO;
443         }                                         444         }
444         return ERR_PTR(err);                      445         return ERR_PTR(err);
445 }                                                 446 }
446                                                   447 
447 static inline struct buffer_head *                448 static inline struct buffer_head *
448 affs_getzeroblk_ino(struct inode *inode, int b    449 affs_getzeroblk_ino(struct inode *inode, int block)
449 {                                                 450 {
450         struct buffer_head *bh, tmp_bh;           451         struct buffer_head *bh, tmp_bh;
451         int err;                                  452         int err;
452                                                   453 
453         tmp_bh.b_state = 0;                       454         tmp_bh.b_state = 0;
454         err = affs_get_block(inode, block, &tm    455         err = affs_get_block(inode, block, &tmp_bh, 1);
455         if (!err) {                               456         if (!err) {
456                 bh = affs_getzeroblk(inode->i_    457                 bh = affs_getzeroblk(inode->i_sb, tmp_bh.b_blocknr);
457                 if (bh) {                         458                 if (bh) {
458                         bh->b_state |= tmp_bh.    459                         bh->b_state |= tmp_bh.b_state;
459                         return bh;                460                         return bh;
460                 }                                 461                 }
461                 err = -EIO;                       462                 err = -EIO;
462         }                                         463         }
463         return ERR_PTR(err);                      464         return ERR_PTR(err);
464 }                                                 465 }
465                                                   466 
466 static inline struct buffer_head *                467 static inline struct buffer_head *
467 affs_getemptyblk_ino(struct inode *inode, int     468 affs_getemptyblk_ino(struct inode *inode, int block)
468 {                                                 469 {
469         struct buffer_head *bh, tmp_bh;           470         struct buffer_head *bh, tmp_bh;
470         int err;                                  471         int err;
471                                                   472 
472         tmp_bh.b_state = 0;                       473         tmp_bh.b_state = 0;
473         err = affs_get_block(inode, block, &tm    474         err = affs_get_block(inode, block, &tmp_bh, 1);
474         if (!err) {                               475         if (!err) {
475                 bh = affs_getemptyblk(inode->i    476                 bh = affs_getemptyblk(inode->i_sb, tmp_bh.b_blocknr);
476                 if (bh) {                         477                 if (bh) {
477                         bh->b_state |= tmp_bh.    478                         bh->b_state |= tmp_bh.b_state;
478                         return bh;                479                         return bh;
479                 }                                 480                 }
480                 err = -EIO;                       481                 err = -EIO;
481         }                                         482         }
482         return ERR_PTR(err);                      483         return ERR_PTR(err);
483 }                                                 484 }
484                                                   485 
485 static int                                        486 static int
486 affs_do_readpage_ofs(struct file *file, struct    487 affs_do_readpage_ofs(struct file *file, struct page *page, unsigned from, unsigned to)
487 {                                                 488 {
488         struct inode *inode = page->mapping->h    489         struct inode *inode = page->mapping->host;
489         struct super_block *sb = inode->i_sb;     490         struct super_block *sb = inode->i_sb;
490         struct buffer_head *bh;                   491         struct buffer_head *bh;
491         char *data;                               492         char *data;
492         u32 bidx, boff, bsize;                    493         u32 bidx, boff, bsize;
493         u32 tmp;                                  494         u32 tmp;
494                                                   495 
495         pr_debug("AFFS: read_page(%u, %ld, %d,    496         pr_debug("AFFS: read_page(%u, %ld, %d, %d)\n", (u32)inode->i_ino, page->index, from, to);
496         if (from > to || to > PAGE_CACHE_SIZE) !! 497         BUG_ON(from > to || to > PAGE_CACHE_SIZE);
497                 BUG();                         << 
498         kmap(page);                               498         kmap(page);
499         data = page_address(page);                499         data = page_address(page);
500         bsize = AFFS_SB(sb)->s_data_blksize;      500         bsize = AFFS_SB(sb)->s_data_blksize;
501         tmp = (page->index << PAGE_CACHE_SHIFT    501         tmp = (page->index << PAGE_CACHE_SHIFT) + from;
502         bidx = tmp / bsize;                       502         bidx = tmp / bsize;
503         boff = tmp % bsize;                       503         boff = tmp % bsize;
504                                                   504 
505         while (from < to) {                       505         while (from < to) {
506                 bh = affs_bread_ino(inode, bid    506                 bh = affs_bread_ino(inode, bidx, 0);
507                 if (IS_ERR(bh))                   507                 if (IS_ERR(bh))
508                         return PTR_ERR(bh);       508                         return PTR_ERR(bh);
509                 tmp = min(bsize - boff, to - f    509                 tmp = min(bsize - boff, to - from);
510                 if (from + tmp > to || tmp > b !! 510                 BUG_ON(from + tmp > to || tmp > bsize);
511                         BUG();                 << 
512                 memcpy(data + from, AFFS_DATA(    511                 memcpy(data + from, AFFS_DATA(bh) + boff, tmp);
513                 affs_brelse(bh);                  512                 affs_brelse(bh);
514                 bidx++;                           513                 bidx++;
515                 from += tmp;                      514                 from += tmp;
516                 boff = 0;                         515                 boff = 0;
517         }                                         516         }
518         flush_dcache_page(page);                  517         flush_dcache_page(page);
519         kunmap(page);                             518         kunmap(page);
520         return 0;                                 519         return 0;
521 }                                                 520 }
522                                                   521 
523 static int                                        522 static int
524 affs_extent_file_ofs(struct inode *inode, u32     523 affs_extent_file_ofs(struct inode *inode, u32 newsize)
525 {                                                 524 {
526         struct super_block *sb = inode->i_sb;     525         struct super_block *sb = inode->i_sb;
527         struct buffer_head *bh, *prev_bh;         526         struct buffer_head *bh, *prev_bh;
528         u32 bidx, boff;                           527         u32 bidx, boff;
529         u32 size, bsize;                          528         u32 size, bsize;
530         u32 tmp;                                  529         u32 tmp;
531                                                   530 
532         pr_debug("AFFS: extent_file(%u, %d)\n"    531         pr_debug("AFFS: extent_file(%u, %d)\n", (u32)inode->i_ino, newsize);
533         bsize = AFFS_SB(sb)->s_data_blksize;      532         bsize = AFFS_SB(sb)->s_data_blksize;
534         bh = NULL;                                533         bh = NULL;
535         size = AFFS_I(inode)->mmu_private;        534         size = AFFS_I(inode)->mmu_private;
536         bidx = size / bsize;                      535         bidx = size / bsize;
537         boff = size % bsize;                      536         boff = size % bsize;
538         if (boff) {                               537         if (boff) {
539                 bh = affs_bread_ino(inode, bid    538                 bh = affs_bread_ino(inode, bidx, 0);
540                 if (IS_ERR(bh))                   539                 if (IS_ERR(bh))
541                         return PTR_ERR(bh);       540                         return PTR_ERR(bh);
542                 tmp = min(bsize - boff, newsiz    541                 tmp = min(bsize - boff, newsize - size);
543                 if (boff + tmp > bsize || tmp  !! 542                 BUG_ON(boff + tmp > bsize || tmp > bsize);
544                         BUG();                 << 
545                 memset(AFFS_DATA(bh) + boff, 0    543                 memset(AFFS_DATA(bh) + boff, 0, tmp);
546                 AFFS_DATA_HEAD(bh)->size = cpu !! 544                 be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
547                 affs_fix_checksum(sb, bh);        545                 affs_fix_checksum(sb, bh);
548                 mark_buffer_dirty_inode(bh, in    546                 mark_buffer_dirty_inode(bh, inode);
549                 size += tmp;                      547                 size += tmp;
550                 bidx++;                           548                 bidx++;
551         } else if (bidx) {                        549         } else if (bidx) {
552                 bh = affs_bread_ino(inode, bid    550                 bh = affs_bread_ino(inode, bidx - 1, 0);
553                 if (IS_ERR(bh))                   551                 if (IS_ERR(bh))
554                         return PTR_ERR(bh);       552                         return PTR_ERR(bh);
555         }                                         553         }
556                                                   554 
557         while (size < newsize) {                  555         while (size < newsize) {
558                 prev_bh = bh;                     556                 prev_bh = bh;
559                 bh = affs_getzeroblk_ino(inode    557                 bh = affs_getzeroblk_ino(inode, bidx);
560                 if (IS_ERR(bh))                   558                 if (IS_ERR(bh))
561                         goto out;                 559                         goto out;
562                 tmp = min(bsize, newsize - siz    560                 tmp = min(bsize, newsize - size);
563                 if (tmp > bsize)               !! 561                 BUG_ON(tmp > bsize);
564                         BUG();                 << 
565                 AFFS_DATA_HEAD(bh)->ptype = cp    562                 AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
566                 AFFS_DATA_HEAD(bh)->key = cpu_    563                 AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
567                 AFFS_DATA_HEAD(bh)->sequence =    564                 AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
568                 AFFS_DATA_HEAD(bh)->size = cpu    565                 AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
569                 affs_fix_checksum(sb, bh);        566                 affs_fix_checksum(sb, bh);
570                 bh->b_state &= ~(1UL << BH_New    567                 bh->b_state &= ~(1UL << BH_New);
571                 mark_buffer_dirty_inode(bh, in    568                 mark_buffer_dirty_inode(bh, inode);
572                 if (prev_bh) {                    569                 if (prev_bh) {
573                         u32 tmp = be32_to_cpu(    570                         u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
574                         if (tmp)                  571                         if (tmp)
575                                 affs_warning(s    572                                 affs_warning(sb, "extent_file_ofs", "next block already set for %d (%d)", bidx, tmp);
576                         AFFS_DATA_HEAD(prev_bh    573                         AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
577                         affs_adjust_checksum(p    574                         affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
578                         mark_buffer_dirty_inod    575                         mark_buffer_dirty_inode(prev_bh, inode);
579                         affs_brelse(prev_bh);     576                         affs_brelse(prev_bh);
580                 }                                 577                 }
581                 size += bsize;                    578                 size += bsize;
582                 bidx++;                           579                 bidx++;
583         }                                         580         }
584         affs_brelse(bh);                          581         affs_brelse(bh);
585         inode->i_size = AFFS_I(inode)->mmu_pri    582         inode->i_size = AFFS_I(inode)->mmu_private = newsize;
586         return 0;                                 583         return 0;
587                                                   584 
588 out:                                              585 out:
589         inode->i_size = AFFS_I(inode)->mmu_pri    586         inode->i_size = AFFS_I(inode)->mmu_private = newsize;
590         return PTR_ERR(bh);                       587         return PTR_ERR(bh);
591 }                                                 588 }
592                                                   589 
593 static int                                        590 static int
594 affs_readpage_ofs(struct file *file, struct pa    591 affs_readpage_ofs(struct file *file, struct page *page)
595 {                                                 592 {
596         struct inode *inode = page->mapping->h    593         struct inode *inode = page->mapping->host;
597         u32 to;                                   594         u32 to;
598         int err;                                  595         int err;
599                                                   596 
600         pr_debug("AFFS: read_page(%u, %ld)\n",    597         pr_debug("AFFS: read_page(%u, %ld)\n", (u32)inode->i_ino, page->index);
601         to = PAGE_CACHE_SIZE;                     598         to = PAGE_CACHE_SIZE;
602         if (((page->index + 1) << PAGE_CACHE_S    599         if (((page->index + 1) << PAGE_CACHE_SHIFT) > inode->i_size) {
603                 to = inode->i_size & ~PAGE_CAC    600                 to = inode->i_size & ~PAGE_CACHE_MASK;
604                 memset(page_address(page) + to    601                 memset(page_address(page) + to, 0, PAGE_CACHE_SIZE - to);
605         }                                         602         }
606                                                   603 
607         err = affs_do_readpage_ofs(file, page,    604         err = affs_do_readpage_ofs(file, page, 0, to);
608         if (!err)                                 605         if (!err)
609                 SetPageUptodate(page);            606                 SetPageUptodate(page);
610         unlock_page(page);                        607         unlock_page(page);
611         return err;                               608         return err;
612 }                                                 609 }
613                                                   610 
614 static int affs_write_begin_ofs(struct file *f    611 static int affs_write_begin_ofs(struct file *file, struct address_space *mapping,
615                                 loff_t pos, un    612                                 loff_t pos, unsigned len, unsigned flags,
616                                 struct page **    613                                 struct page **pagep, void **fsdata)
617 {                                                 614 {
618         struct inode *inode = mapping->host;      615         struct inode *inode = mapping->host;
619         struct page *page;                        616         struct page *page;
620         pgoff_t index;                            617         pgoff_t index;
621         int err = 0;                              618         int err = 0;
622                                                   619 
623         pr_debug("AFFS: write_begin(%u, %llu,     620         pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
624         if (pos > AFFS_I(inode)->mmu_private)     621         if (pos > AFFS_I(inode)->mmu_private) {
625                 /* XXX: this probably leaves a    622                 /* XXX: this probably leaves a too-big i_size in case of
626                  * failure. Should really be u    623                  * failure. Should really be updating i_size at write_end time
627                  */                               624                  */
628                 err = affs_extent_file_ofs(ino    625                 err = affs_extent_file_ofs(inode, pos);
629                 if (err)                          626                 if (err)
630                         return err;               627                         return err;
631         }                                         628         }
632                                                   629 
633         index = pos >> PAGE_CACHE_SHIFT;          630         index = pos >> PAGE_CACHE_SHIFT;
634         page = __grab_cache_page(mapping, inde !! 631         page = grab_cache_page_write_begin(mapping, index, flags);
635         if (!page)                                632         if (!page)
636                 return -ENOMEM;                   633                 return -ENOMEM;
637         *pagep = page;                            634         *pagep = page;
638                                                   635 
639         if (PageUptodate(page))                   636         if (PageUptodate(page))
640                 return 0;                         637                 return 0;
641                                                   638 
642         /* XXX: inefficient but safe in the fa    639         /* XXX: inefficient but safe in the face of short writes */
643         err = affs_do_readpage_ofs(file, page,    640         err = affs_do_readpage_ofs(file, page, 0, PAGE_CACHE_SIZE);
644         if (err) {                                641         if (err) {
645                 unlock_page(page);                642                 unlock_page(page);
646                 page_cache_release(page);         643                 page_cache_release(page);
647         }                                         644         }
648         return err;                               645         return err;
649 }                                                 646 }
650                                                   647 
651 static int affs_write_end_ofs(struct file *fil    648 static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
652                                 loff_t pos, un    649                                 loff_t pos, unsigned len, unsigned copied,
653                                 struct page *p    650                                 struct page *page, void *fsdata)
654 {                                                 651 {
655         struct inode *inode = mapping->host;      652         struct inode *inode = mapping->host;
656         struct super_block *sb = inode->i_sb;     653         struct super_block *sb = inode->i_sb;
657         struct buffer_head *bh, *prev_bh;         654         struct buffer_head *bh, *prev_bh;
658         char *data;                               655         char *data;
659         u32 bidx, boff, bsize;                    656         u32 bidx, boff, bsize;
660         unsigned from, to;                        657         unsigned from, to;
661         u32 tmp;                                  658         u32 tmp;
662         int written;                              659         int written;
663                                                   660 
664         from = pos & (PAGE_CACHE_SIZE - 1);       661         from = pos & (PAGE_CACHE_SIZE - 1);
665         to = pos + len;                           662         to = pos + len;
666         /*                                        663         /*
667          * XXX: not sure if this can handle sh    664          * XXX: not sure if this can handle short copies (len < copied), but
668          * we don't have to, because the page     665          * we don't have to, because the page should always be uptodate here,
669          * due to write_begin.                    666          * due to write_begin.
670          */                                       667          */
671                                                   668 
672         pr_debug("AFFS: write_begin(%u, %llu,     669         pr_debug("AFFS: write_begin(%u, %llu, %llu)\n", (u32)inode->i_ino, (unsigned long long)pos, (unsigned long long)pos + len);
673         bsize = AFFS_SB(sb)->s_data_blksize;      670         bsize = AFFS_SB(sb)->s_data_blksize;
674         data = page_address(page);                671         data = page_address(page);
675                                                   672 
676         bh = NULL;                                673         bh = NULL;
677         written = 0;                              674         written = 0;
678         tmp = (page->index << PAGE_CACHE_SHIFT    675         tmp = (page->index << PAGE_CACHE_SHIFT) + from;
679         bidx = tmp / bsize;                       676         bidx = tmp / bsize;
680         boff = tmp % bsize;                       677         boff = tmp % bsize;
681         if (boff) {                               678         if (boff) {
682                 bh = affs_bread_ino(inode, bid    679                 bh = affs_bread_ino(inode, bidx, 0);
683                 if (IS_ERR(bh))                   680                 if (IS_ERR(bh))
684                         return PTR_ERR(bh);       681                         return PTR_ERR(bh);
685                 tmp = min(bsize - boff, to - f    682                 tmp = min(bsize - boff, to - from);
686                 if (boff + tmp > bsize || tmp  !! 683                 BUG_ON(boff + tmp > bsize || tmp > bsize);
687                         BUG();                 << 
688                 memcpy(AFFS_DATA(bh) + boff, d    684                 memcpy(AFFS_DATA(bh) + boff, data + from, tmp);
689                 AFFS_DATA_HEAD(bh)->size = cpu !! 685                 be32_add_cpu(&AFFS_DATA_HEAD(bh)->size, tmp);
690                 affs_fix_checksum(sb, bh);        686                 affs_fix_checksum(sb, bh);
691                 mark_buffer_dirty_inode(bh, in    687                 mark_buffer_dirty_inode(bh, inode);
692                 written += tmp;                   688                 written += tmp;
693                 from += tmp;                      689                 from += tmp;
694                 bidx++;                           690                 bidx++;
695         } else if (bidx) {                        691         } else if (bidx) {
696                 bh = affs_bread_ino(inode, bid    692                 bh = affs_bread_ino(inode, bidx - 1, 0);
697                 if (IS_ERR(bh))                   693                 if (IS_ERR(bh))
698                         return PTR_ERR(bh);       694                         return PTR_ERR(bh);
699         }                                         695         }
700         while (from + bsize <= to) {              696         while (from + bsize <= to) {
701                 prev_bh = bh;                     697                 prev_bh = bh;
702                 bh = affs_getemptyblk_ino(inod    698                 bh = affs_getemptyblk_ino(inode, bidx);
703                 if (IS_ERR(bh))                   699                 if (IS_ERR(bh))
704                         goto out;                 700                         goto out;
705                 memcpy(AFFS_DATA(bh), data + f    701                 memcpy(AFFS_DATA(bh), data + from, bsize);
706                 if (buffer_new(bh)) {             702                 if (buffer_new(bh)) {
707                         AFFS_DATA_HEAD(bh)->pt    703                         AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
708                         AFFS_DATA_HEAD(bh)->ke    704                         AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
709                         AFFS_DATA_HEAD(bh)->se    705                         AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
710                         AFFS_DATA_HEAD(bh)->si    706                         AFFS_DATA_HEAD(bh)->size = cpu_to_be32(bsize);
711                         AFFS_DATA_HEAD(bh)->ne    707                         AFFS_DATA_HEAD(bh)->next = 0;
712                         bh->b_state &= ~(1UL <    708                         bh->b_state &= ~(1UL << BH_New);
713                         if (prev_bh) {            709                         if (prev_bh) {
714                                 u32 tmp = be32    710                                 u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
715                                 if (tmp)          711                                 if (tmp)
716                                         affs_w    712                                         affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
717                                 AFFS_DATA_HEAD    713                                 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
718                                 affs_adjust_ch    714                                 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
719                                 mark_buffer_di    715                                 mark_buffer_dirty_inode(prev_bh, inode);
720                         }                         716                         }
721                 }                                 717                 }
722                 affs_brelse(prev_bh);             718                 affs_brelse(prev_bh);
723                 affs_fix_checksum(sb, bh);        719                 affs_fix_checksum(sb, bh);
724                 mark_buffer_dirty_inode(bh, in    720                 mark_buffer_dirty_inode(bh, inode);
725                 written += bsize;                 721                 written += bsize;
726                 from += bsize;                    722                 from += bsize;
727                 bidx++;                           723                 bidx++;
728         }                                         724         }
729         if (from < to) {                          725         if (from < to) {
730                 prev_bh = bh;                     726                 prev_bh = bh;
731                 bh = affs_bread_ino(inode, bid    727                 bh = affs_bread_ino(inode, bidx, 1);
732                 if (IS_ERR(bh))                   728                 if (IS_ERR(bh))
733                         goto out;                 729                         goto out;
734                 tmp = min(bsize, to - from);      730                 tmp = min(bsize, to - from);
735                 if (tmp > bsize)               !! 731                 BUG_ON(tmp > bsize);
736                         BUG();                 << 
737                 memcpy(AFFS_DATA(bh), data + f    732                 memcpy(AFFS_DATA(bh), data + from, tmp);
738                 if (buffer_new(bh)) {             733                 if (buffer_new(bh)) {
739                         AFFS_DATA_HEAD(bh)->pt    734                         AFFS_DATA_HEAD(bh)->ptype = cpu_to_be32(T_DATA);
740                         AFFS_DATA_HEAD(bh)->ke    735                         AFFS_DATA_HEAD(bh)->key = cpu_to_be32(inode->i_ino);
741                         AFFS_DATA_HEAD(bh)->se    736                         AFFS_DATA_HEAD(bh)->sequence = cpu_to_be32(bidx);
742                         AFFS_DATA_HEAD(bh)->si    737                         AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
743                         AFFS_DATA_HEAD(bh)->ne    738                         AFFS_DATA_HEAD(bh)->next = 0;
744                         bh->b_state &= ~(1UL <    739                         bh->b_state &= ~(1UL << BH_New);
745                         if (prev_bh) {            740                         if (prev_bh) {
746                                 u32 tmp = be32    741                                 u32 tmp = be32_to_cpu(AFFS_DATA_HEAD(prev_bh)->next);
747                                 if (tmp)          742                                 if (tmp)
748                                         affs_w    743                                         affs_warning(sb, "commit_write_ofs", "next block already set for %d (%d)", bidx, tmp);
749                                 AFFS_DATA_HEAD    744                                 AFFS_DATA_HEAD(prev_bh)->next = cpu_to_be32(bh->b_blocknr);
750                                 affs_adjust_ch    745                                 affs_adjust_checksum(prev_bh, bh->b_blocknr - tmp);
751                                 mark_buffer_di    746                                 mark_buffer_dirty_inode(prev_bh, inode);
752                         }                         747                         }
753                 } else if (be32_to_cpu(AFFS_DA    748                 } else if (be32_to_cpu(AFFS_DATA_HEAD(bh)->size) < tmp)
754                         AFFS_DATA_HEAD(bh)->si    749                         AFFS_DATA_HEAD(bh)->size = cpu_to_be32(tmp);
755                 affs_brelse(prev_bh);             750                 affs_brelse(prev_bh);
756                 affs_fix_checksum(sb, bh);        751                 affs_fix_checksum(sb, bh);
757                 mark_buffer_dirty_inode(bh, in    752                 mark_buffer_dirty_inode(bh, inode);
758                 written += tmp;                   753                 written += tmp;
759                 from += tmp;                      754                 from += tmp;
760                 bidx++;                           755                 bidx++;
761         }                                         756         }
762         SetPageUptodate(page);                    757         SetPageUptodate(page);
763                                                   758 
764 done:                                             759 done:
765         affs_brelse(bh);                          760         affs_brelse(bh);
766         tmp = (page->index << PAGE_CACHE_SHIFT    761         tmp = (page->index << PAGE_CACHE_SHIFT) + from;
767         if (tmp > inode->i_size)                  762         if (tmp > inode->i_size)
768                 inode->i_size = AFFS_I(inode)-    763                 inode->i_size = AFFS_I(inode)->mmu_private = tmp;
769                                                   764 
770         unlock_page(page);                        765         unlock_page(page);
771         page_cache_release(page);                 766         page_cache_release(page);
772                                                   767 
773         return written;                           768         return written;
774                                                   769 
775 out:                                              770 out:
776         bh = prev_bh;                             771         bh = prev_bh;
777         if (!written)                             772         if (!written)
778                 written = PTR_ERR(bh);            773                 written = PTR_ERR(bh);
779         goto done;                                774         goto done;
780 }                                                 775 }
781                                                   776 
782 const struct address_space_operations affs_aop    777 const struct address_space_operations affs_aops_ofs = {
783         .readpage = affs_readpage_ofs,            778         .readpage = affs_readpage_ofs,
784         //.writepage = affs_writepage_ofs,        779         //.writepage = affs_writepage_ofs,
785         //.sync_page = affs_sync_page_ofs,        780         //.sync_page = affs_sync_page_ofs,
786         .write_begin = affs_write_begin_ofs,      781         .write_begin = affs_write_begin_ofs,
787         .write_end = affs_write_end_ofs           782         .write_end = affs_write_end_ofs
788 };                                                783 };
789                                                   784 
790 /* Free any preallocated blocks. */               785 /* Free any preallocated blocks. */
791                                                   786 
792 void                                              787 void
793 affs_free_prealloc(struct inode *inode)           788 affs_free_prealloc(struct inode *inode)
794 {                                                 789 {
795         struct super_block *sb = inode->i_sb;     790         struct super_block *sb = inode->i_sb;
796                                                   791 
797         pr_debug("AFFS: free_prealloc(ino=%lu)    792         pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino);
798                                                   793 
799         while (AFFS_I(inode)->i_pa_cnt) {         794         while (AFFS_I(inode)->i_pa_cnt) {
800                 AFFS_I(inode)->i_pa_cnt--;        795                 AFFS_I(inode)->i_pa_cnt--;
801                 affs_free_block(sb, ++AFFS_I(i    796                 affs_free_block(sb, ++AFFS_I(inode)->i_lastalloc);
802         }                                         797         }
803 }                                                 798 }
804                                                   799 
805 /* Truncate (or enlarge) a file to the request    800 /* Truncate (or enlarge) a file to the requested size. */
806                                                   801 
807 void                                              802 void
808 affs_truncate(struct inode *inode)                803 affs_truncate(struct inode *inode)
809 {                                                 804 {
810         struct super_block *sb = inode->i_sb;     805         struct super_block *sb = inode->i_sb;
811         u32 ext, ext_key;                         806         u32 ext, ext_key;
812         u32 last_blk, blkcnt, blk;                807         u32 last_blk, blkcnt, blk;
813         u32 size;                                 808         u32 size;
814         struct buffer_head *ext_bh;               809         struct buffer_head *ext_bh;
815         int i;                                    810         int i;
816                                                   811 
817         pr_debug("AFFS: truncate(inode=%d, old    812         pr_debug("AFFS: truncate(inode=%d, oldsize=%u, newsize=%u)\n",
818                  (u32)inode->i_ino, (u32)AFFS_    813                  (u32)inode->i_ino, (u32)AFFS_I(inode)->mmu_private, (u32)inode->i_size);
819                                                   814 
820         last_blk = 0;                             815         last_blk = 0;
821         ext = 0;                                  816         ext = 0;
822         if (inode->i_size) {                      817         if (inode->i_size) {
823                 last_blk = ((u32)inode->i_size    818                 last_blk = ((u32)inode->i_size - 1) / AFFS_SB(sb)->s_data_blksize;
824                 ext = last_blk / AFFS_SB(sb)->    819                 ext = last_blk / AFFS_SB(sb)->s_hashsize;
825         }                                         820         }
826                                                   821 
827         if (inode->i_size > AFFS_I(inode)->mmu    822         if (inode->i_size > AFFS_I(inode)->mmu_private) {
828                 struct address_space *mapping     823                 struct address_space *mapping = inode->i_mapping;
829                 struct page *page;                824                 struct page *page;
830                 void *fsdata;                     825                 void *fsdata;
831                 u32 size = inode->i_size;         826                 u32 size = inode->i_size;
832                 int res;                          827                 int res;
833                                                   828 
834                 res = mapping->a_ops->write_be    829                 res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata);
835                 if (!res)                         830                 if (!res)
836                         res = mapping->a_ops->    831                         res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata);
                                                   >> 832                 else
                                                   >> 833                         inode->i_size = AFFS_I(inode)->mmu_private;
837                 mark_inode_dirty(inode);          834                 mark_inode_dirty(inode);
838                 return;                           835                 return;
839         } else if (inode->i_size == AFFS_I(ino    836         } else if (inode->i_size == AFFS_I(inode)->mmu_private)
840                 return;                           837                 return;
841                                                   838 
842         // lock cache                             839         // lock cache
843         ext_bh = affs_get_extblock(inode, ext)    840         ext_bh = affs_get_extblock(inode, ext);
844         if (IS_ERR(ext_bh)) {                     841         if (IS_ERR(ext_bh)) {
845                 affs_warning(sb, "truncate", "    842                 affs_warning(sb, "truncate", "unexpected read error for ext block %u (%d)",
846                              ext, PTR_ERR(ext_    843                              ext, PTR_ERR(ext_bh));
847                 return;                           844                 return;
848         }                                         845         }
849         if (AFFS_I(inode)->i_lc) {                846         if (AFFS_I(inode)->i_lc) {
850                 /* clear linear cache */          847                 /* clear linear cache */
851                 i = (ext + 1) >> AFFS_I(inode)    848                 i = (ext + 1) >> AFFS_I(inode)->i_lc_shift;
852                 if (AFFS_I(inode)->i_lc_size >    849                 if (AFFS_I(inode)->i_lc_size > i) {
853                         AFFS_I(inode)->i_lc_si    850                         AFFS_I(inode)->i_lc_size = i;
854                         for (; i < AFFS_LC_SIZ    851                         for (; i < AFFS_LC_SIZE; i++)
855                                 AFFS_I(inode)-    852                                 AFFS_I(inode)->i_lc[i] = 0;
856                 }                                 853                 }
857                 /* clear associative cache */     854                 /* clear associative cache */
858                 for (i = 0; i < AFFS_AC_SIZE;     855                 for (i = 0; i < AFFS_AC_SIZE; i++)
859                         if (AFFS_I(inode)->i_a    856                         if (AFFS_I(inode)->i_ac[i].ext >= ext)
860                                 AFFS_I(inode)-    857                                 AFFS_I(inode)->i_ac[i].ext = 0;
861         }                                         858         }
862         ext_key = be32_to_cpu(AFFS_TAIL(sb, ex    859         ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
863                                                   860 
864         blkcnt = AFFS_I(inode)->i_blkcnt;         861         blkcnt = AFFS_I(inode)->i_blkcnt;
865         i = 0;                                    862         i = 0;
866         blk = last_blk;                           863         blk = last_blk;
867         if (inode->i_size) {                      864         if (inode->i_size) {
868                 i = last_blk % AFFS_SB(sb)->s_    865                 i = last_blk % AFFS_SB(sb)->s_hashsize + 1;
869                 blk++;                            866                 blk++;
870         } else                                    867         } else
871                 AFFS_HEAD(ext_bh)->first_data     868                 AFFS_HEAD(ext_bh)->first_data = 0;
                                                   >> 869         AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i);
872         size = AFFS_SB(sb)->s_hashsize;           870         size = AFFS_SB(sb)->s_hashsize;
873         if (size > blkcnt - blk + i)              871         if (size > blkcnt - blk + i)
874                 size = blkcnt - blk + i;          872                 size = blkcnt - blk + i;
875         for (; i < size; i++, blk++) {            873         for (; i < size; i++, blk++) {
876                 affs_free_block(sb, be32_to_cp    874                 affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
877                 AFFS_BLOCK(sb, ext_bh, i) = 0;    875                 AFFS_BLOCK(sb, ext_bh, i) = 0;
878         }                                         876         }
879         AFFS_TAIL(sb, ext_bh)->extension = 0;     877         AFFS_TAIL(sb, ext_bh)->extension = 0;
880         affs_fix_checksum(sb, ext_bh);            878         affs_fix_checksum(sb, ext_bh);
881         mark_buffer_dirty_inode(ext_bh, inode)    879         mark_buffer_dirty_inode(ext_bh, inode);
882         affs_brelse(ext_bh);                      880         affs_brelse(ext_bh);
883                                                   881 
884         if (inode->i_size) {                      882         if (inode->i_size) {
885                 AFFS_I(inode)->i_blkcnt = last    883                 AFFS_I(inode)->i_blkcnt = last_blk + 1;
886                 AFFS_I(inode)->i_extcnt = ext     884                 AFFS_I(inode)->i_extcnt = ext + 1;
887                 if (AFFS_SB(sb)->s_flags & SF_    885                 if (AFFS_SB(sb)->s_flags & SF_OFS) {
888                         struct buffer_head *bh    886                         struct buffer_head *bh = affs_bread_ino(inode, last_blk, 0);
889                         u32 tmp;                  887                         u32 tmp;
890                         if (IS_ERR(ext_bh)) {     888                         if (IS_ERR(ext_bh)) {
891                                 affs_warning(s    889                                 affs_warning(sb, "truncate", "unexpected read error for last block %u (%d)",
892                                              e    890                                              ext, PTR_ERR(ext_bh));
893                                 return;           891                                 return;
894                         }                         892                         }
895                         tmp = be32_to_cpu(AFFS    893                         tmp = be32_to_cpu(AFFS_DATA_HEAD(bh)->next);
896                         AFFS_DATA_HEAD(bh)->ne    894                         AFFS_DATA_HEAD(bh)->next = 0;
897                         affs_adjust_checksum(b    895                         affs_adjust_checksum(bh, -tmp);
898                         affs_brelse(bh);          896                         affs_brelse(bh);
899                 }                                 897                 }
900         } else {                                  898         } else {
901                 AFFS_I(inode)->i_blkcnt = 0;      899                 AFFS_I(inode)->i_blkcnt = 0;
902                 AFFS_I(inode)->i_extcnt = 1;      900                 AFFS_I(inode)->i_extcnt = 1;
903         }                                         901         }
904         AFFS_I(inode)->mmu_private = inode->i_    902         AFFS_I(inode)->mmu_private = inode->i_size;
905         // unlock cache                           903         // unlock cache
906                                                   904 
907         while (ext_key) {                         905         while (ext_key) {
908                 ext_bh = affs_bread(sb, ext_ke    906                 ext_bh = affs_bread(sb, ext_key);
909                 size = AFFS_SB(sb)->s_hashsize    907                 size = AFFS_SB(sb)->s_hashsize;
910                 if (size > blkcnt - blk)          908                 if (size > blkcnt - blk)
911                         size = blkcnt - blk;      909                         size = blkcnt - blk;
912                 for (i = 0; i < size; i++, blk    910                 for (i = 0; i < size; i++, blk++)
913                         affs_free_block(sb, be    911                         affs_free_block(sb, be32_to_cpu(AFFS_BLOCK(sb, ext_bh, i)));
914                 affs_free_block(sb, ext_key);     912                 affs_free_block(sb, ext_key);
915                 ext_key = be32_to_cpu(AFFS_TAI    913                 ext_key = be32_to_cpu(AFFS_TAIL(sb, ext_bh)->extension);
916                 affs_brelse(ext_bh);              914                 affs_brelse(ext_bh);
917         }                                         915         }
918         affs_free_prealloc(inode);                916         affs_free_prealloc(inode);
919 }                                                 917 }
                                                   >> 918 
                                                   >> 919 int affs_file_fsync(struct file *filp, struct dentry *dentry, int datasync)
                                                   >> 920 {
                                                   >> 921         struct inode * inode = dentry->d_inode;
                                                   >> 922         int ret, err;
                                                   >> 923 
                                                   >> 924         ret = write_inode_now(inode, 0);
                                                   >> 925         err = sync_blockdev(inode->i_sb->s_bdev);
                                                   >> 926         if (!ret)
                                                   >> 927                 ret = err;
                                                   >> 928         return ret;
                                                   >> 929 }
920                                                   930 
  This page was automatically generated by the LXR engine.