From a05d850679d747d0321a745299b626d87c943464 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Fri, 4 Mar 2011 12:47:30 +1100 Subject: [PATCH] roll: permit minimal mini-block handling for regular files. If the miniblock is at the start of the file, write it out to the file. This allows inodes which contain data to commit that data. Signed-off-by: NeilBrown --- roll.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/roll.c b/roll.c index 937983a..39cee18 100644 --- a/roll.c +++ b/roll.c @@ -241,6 +241,8 @@ roll_mini(struct fs *fs, int fsnum, int inum, int trunc, int err = 0; void *buf; char *name; + struct page *page; + void *fsdata; dprintk("Roll Mini %d/%d/%lu/%d,%d\n", fsnum, inum, (unsigned long) bnum, @@ -253,9 +255,11 @@ roll_mini(struct fs *fs, int fsnum, int inum, int trunc, * index update and data update are not (data update must * go through the file). Implied creation requires * orphan handling - * regular-files: could just over-write data, possibly extending size - * but there doesn't seem to be any reason to create such updates - * so we don't bother to try handling them. + * regular-files: We don't create miniblocks for regular files, + * but we might write an inode with embedded data and want + * that data to be safe. When those inodes are found, at + * miniblock is synthesised from the data so we need to + * handle it. * symlink,dev,pipe: as with reg-files * directory: add/remove entries. Each miniblock has an address and * identifies a name, an inode number, and one of: @@ -349,6 +353,29 @@ roll_mini(struct fs *fs, int fsnum, int inum, int trunc, name = data + 4; err = lafs_dir_roll_mini(inode, bnum, offset, inum, name, len-4); break; + + case TypeFile: + case TypeSymlink: + case TypeSpecial: + if (bnum != 0 || offset != 0) { + /* We currently only expect update at the very start + * of a (small) file. + * So reject anything else. + */ + err = -EIO; + break; + } + err = pagecache_write_begin(NULL, inode->i_mapping, + 0, len, 0, + &page, &fsdata); + if (!err) { + char *b = kmap_atomic(page, KM_USER0); + memcpy(b, data, len); + kunmap_atomic(b, KM_USER0); + pagecache_write_end(NULL, inode->i_mapping, + 0, len, len, page, fsdata); + } + break; } /* We borrow the orphan list to keep a reference on * this inode until all processing is finished -- 2.39.5