]> git.neil.brown.name Git - LaFS.git/commitdiff
roll: permit minimal mini-block handling for regular files.
authorNeilBrown <neilb@suse.de>
Fri, 4 Mar 2011 01:47:30 +0000 (12:47 +1100)
committerNeilBrown <neilb@suse.de>
Fri, 4 Mar 2011 01:47:30 +0000 (12:47 +1100)
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 <neilb@suse.de>
roll.c

diff --git a/roll.c b/roll.c
index 937983a28e9f3e9c63d2e7ac7a48a87592468877..39cee1843304ab5afb8754586b6ed81eb0526739 100644 (file)
--- 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