OK, maybe this revised patch will allow you to delete things after
reaching a volume full condition.  Not tested...

Daniel
diff -r fbdd7c18a67c user/commit.c
--- a/user/commit.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/commit.c	Mon Mar 02 17:32:32 2009 -0800
@@ -242,12 +242,13 @@ static int commit_delta(struct sb *sb)
 	return unstash(sb, &sb->defree, retire_bfree);
 }
 
-void change_begin(struct sb *sb)
+int change_begin(struct sb *sb)
 {
 	down_read(&sb->delta_lock);
+	return 0;
 }
 
-void change_end(struct sb *sb)
+int change_end(struct sb *sb)
 {
 	if (need_delta(sb)) {
 		unsigned delta = sb->delta;
@@ -262,6 +263,7 @@ void change_end(struct sb *sb)
 		up_write(&sb->delta_lock);
 	} else
 		up_read(&sb->delta_lock);
+	return 0;
 }
 
 int bitmap_io(struct buffer_head *buffer, int write)
diff -r fbdd7c18a67c user/filemap.c
--- a/user/filemap.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/filemap.c	Mon Mar 02 17:32:32 2009 -0800
@@ -14,6 +14,13 @@
 #include "kernel/ileaf.c"
 #include "kernel/balloc.c"
 #include "kernel/filemap.c"
+
+int devio(int rw, struct dev *dev, loff_t offset, void *data, unsigned len)
+{
+	return ioabs(dev->fd, data, len, rw, offset);
+}
+
+#include "kernel/commit.c"
 
 /*
  * Extrapolate from single buffer flush or blockread to opportunistic exent IO
@@ -112,8 +119,8 @@ int filemap_extent_io(struct buffer_head
 }
 
 #ifdef build_filemap
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 static void check_created_seg(struct seg *seg)
 {
diff -r fbdd7c18a67c user/ileaf.c
--- a/user/ileaf.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/ileaf.c	Mon Mar 02 17:32:32 2009 -0800
@@ -21,8 +21,8 @@
 #include "kernel/xattr.c"
 #include "kernel/ileaf.c"
 
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 struct ileaf *ileaf_create(struct btree *btree)
 {
diff -r fbdd7c18a67c user/inode.c
--- a/user/inode.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/inode.c	Mon Mar 02 17:32:32 2009 -0800
@@ -293,8 +293,8 @@ void tuxclose(struct inode *inode)
 #include "super.c"
 
 #ifdef build_inode
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 int main(int argc, char *argv[])
 {
diff -r fbdd7c18a67c user/kernel/commit.c
--- a/user/kernel/commit.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/commit.c	Mon Mar 02 17:32:32 2009 -0800
@@ -32,6 +32,7 @@ int load_sb(struct sb *sb)
 	sb->atomgen = from_be_u32(super->atomgen);
 	sb->freeatom = from_be_u32(super->freeatom);
 	sb->dictsize = from_be_u64(super->dictsize);
+	sb->margin = 100; // should be tunable?
 	trace("blocksize %u, blockbits %u, blockmask %08x",
 	      sb->blocksize, sb->blockbits, sb->blockmask);
 	trace("volblocks %Lu, freeblocks %Lu, nextalloc %Lu",
@@ -61,3 +62,40 @@ int load_itable(struct sb *sb)
 	init_btree(itable_btree(sb), sb, unpack_root(iroot_val), &itable_ops);
 	return 0;
 }
+
+#ifdef __KERNEL__
+int reserve_credits(struct sb *sb, unsigned credits)
+{
+	sb->credits += credits;
+	if (sb->margin > 0 && sb->freeblocks < sb->credits + sb->margin) {
+		struct block_device *bdev = vfs_sb(sb)->s_bdev;
+		warn(">>> freeblocks = %Lx, credits = %Lx", (L)sb->freeblocks, (L)sb->credits);
+		sb->margin = -sb->margin;
+		freeze_bdev(bdev);
+		sb->credits = 0;
+		thaw_bdev(bdev, vfs_sb(sb));
+		sb->margin = -sb->margin;
+		warn(">>> nospace = %i", sb->freeblocks < sb->credits + sb->margin);
+		if (sb->freeblocks < sb->credits + sb->margin) {
+			return -ENOSPC;
+		}
+	}
+	return 0;
+}
+
+int change_begin(struct sb *sb)
+{
+	return reserve_credits(sb, 10);
+}
+
+int reduce_begin(struct sb *sb)
+{
+	return 0;
+}
+
+int change_end(struct sb *sb)
+{
+	// <try to return unused credits to pool> //
+	return 0;
+}
+#endif
diff -r fbdd7c18a67c user/kernel/dir.c
--- a/user/kernel/dir.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/dir.c	Mon Mar 02 17:32:32 2009 -0800
@@ -132,7 +132,7 @@ loff_t _tux_create_entry(struct inode *d
 		while (entry <= limit) {
 			if (entry->rec_len == 0) {
 				brelse(buffer);
-				tux_error(dir->i_sb, "zero-length directory entry");
+				warn("[CORRUPTION] Zero length directory record detected!");
 				return -EIO;
 			}
 			name_len = TUX_REC_LEN(entry->name_len);
diff -r fbdd7c18a67c user/kernel/filemap.c
--- a/user/kernel/filemap.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/filemap.c	Mon Mar 02 17:32:32 2009 -0800
@@ -511,7 +511,11 @@ static int tux3_da_write_begin(struct fi
 			       loff_t pos, unsigned len, unsigned flags,
 			       struct page **pagep, void **fsdata)
 {
+	struct sb *sb = tux_sb(mapping->host->i_sb);
+	int err;
 	*pagep = NULL;
+	if ((err = reserve_credits(sb, (len >> sb->blockbits) + 10)))
+		return err;
 	return block_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
 				 tux3_da_get_block);
 }
@@ -519,8 +523,10 @@ static int tux3_writepage(struct page *p
 static int tux3_writepage(struct page *page, struct writeback_control *wbc)
 {
 	struct sb *sb = tux_sb(page->mapping->host->i_sb);
-	change_begin(sb);
-	int err = block_write_full_page(page, tux3_get_block, wbc);
+	int err = change_begin(sb);
+	if (err)
+		return err;
+	err = block_write_full_page(page, tux3_get_block, wbc);
 	change_end(sb);
 	return err;
 }
diff -r fbdd7c18a67c user/kernel/inode.c
--- a/user/kernel/inode.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/inode.c	Mon Mar 02 17:32:32 2009 -0800
@@ -307,7 +307,7 @@ static void tux3_truncate(struct inode *
 	/* FIXME: must fix expand size */
 	WARN_ON(inode->i_size);
 	block_truncate_page(inode->i_mapping, inode->i_size, tux3_get_block);
-	change_begin(sb);
+	reduce_begin(sb);
 	err = tree_chop(&tux_inode(inode)->btree, &del_info, 0);
 	inode->i_blocks = ((inode->i_size + sb->blockmask)
 			   & ~(loff_t)sb->blockmask) >> 9;
@@ -321,7 +321,7 @@ void tux3_delete_inode(struct inode *ino
 	struct sb *sb = tux_sb(inode->i_sb);
 	inum_t inum = tux_inode(inode)->inum;
 
-	change_begin(sb);
+	reduce_begin(sb);
 	truncate_inode_pages(&inode->i_data, 0);
 	if (is_bad_inode(inode)) {
 		clear_inode(inode);
diff -r fbdd7c18a67c user/kernel/namei.c
--- a/user/kernel/namei.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/namei.c	Mon Mar 02 17:32:32 2009 -0800
@@ -66,7 +66,8 @@ static int tux3_mknod(struct inode *dir,
 	if (!huge_valid_dev(rdev))
 		return -EINVAL;
 
-	change_begin(tux_sb(dir->i_sb));
+	if ((err = change_begin(tux_sb(dir->i_sb))))
+		return err;
 	inode = tux_create_inode(dir, mode, rdev);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
@@ -105,8 +106,8 @@ static int tux3_link(struct dentry *old_
 
 	if (inode->i_nlink >= TUX_LINK_MAX)
 		return -EMLINK;
-
-	change_begin(tux_sb(inode->i_sb));
+	if ((err = change_begin(tux_sb(inode->i_sb))))
+		return err;
 	inode->i_ctime = gettime();
 	inode_inc_link_count(inode);
 	atomic_inc(&inode->i_count);
@@ -125,7 +126,8 @@ static int tux3_symlink(struct inode *di
 	struct inode *inode;
 	int err;
 
-	change_begin(tux_sb(dir->i_sb));
+	if ((err = change_begin(tux_sb(dir->i_sb))))
+		return err;
 	inode = tux_create_inode(dir, S_IFLNK | S_IRWXUGO, 0);
 	err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
@@ -146,9 +148,10 @@ static int tux3_unlink(struct inode *dir
 static int tux3_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	change_begin(tux_sb(inode->i_sb));
-	int err = tux_del_dirent(dir, dentry);
-	if (!err) {
+	int err;
+	if ((err = reduce_begin(tux_sb(dir->i_sb))))
+		return err;
+	if (!(tux_del_dirent(dir, dentry))) {
 		inode->i_ctime = dir->i_ctime;
 		inode_dec_link_count(inode);
 	}
@@ -161,19 +164,18 @@ static int tux3_rmdir(struct inode *dir,
 	struct inode *inode = dentry->d_inode;
 	int err;
 
-	err = tux_dir_is_empty(inode);
-	if (!err) {
-		change_begin(tux_sb(inode->i_sb));
-		err = tux_del_dirent(dir, dentry);
-		if (!err) {
-			inode->i_ctime = dir->i_ctime;
-			inode->i_size = 0;
-			clear_nlink(inode);
-			mark_inode_dirty(inode);
-			inode_dec_link_count(dir);
-		}
-		change_end(tux_sb(inode->i_sb));
+	if ((err = tux_dir_is_empty(inode)))
+		return err;
+	if ((err = reduce_begin(tux_sb(dir->i_sb))))
+		return err;
+	if (!(tux_del_dirent(dir, dentry))) {
+		inode->i_ctime = dir->i_ctime;
+		inode->i_size = 0;
+		clear_nlink(inode);
+		mark_inode_dirty(inode);
+		inode_dec_link_count(dir);
 	}
+	change_end(tux_sb(inode->i_sb));
 	return err;
 }
 
@@ -194,7 +196,8 @@ static int tux3_rename(struct inode *old
 	/* FIXME: is this needed? */
 	BUG_ON(from_be_u64(old_entry->inum) != tux_inode(old_inode)->inum);
 
-	change_begin(tux_sb(old_inode->i_sb));
+	if ((err = change_begin(tux_sb(old_dir->i_sb))))
+		return err;
 	if (new_inode) {
 		int old_is_dir = S_ISDIR(old_inode->i_mode);
 		if (old_is_dir) {
diff -r fbdd7c18a67c user/kernel/tux3.h
--- a/user/kernel/tux3.h	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/kernel/tux3.h	Mon Mar 02 17:32:32 2009 -0800
@@ -208,7 +208,7 @@ static inline void flink_last_del(struct
 /* Tux3 disk format */
 
 #define SB_MAGIC_SIZE 8
-#define SB_MAGIC { 't', 'u', 'x', '3', 0xdd, 0x09, 0x02, 0x18 } /* date of latest incompatible sb format */
+#define SB_MAGIC { 't', 'u', 'x', '3', 0xdd, 0x09, 0x02, 0x28 } /* date of latest incompatible sb format */
 /*
  * disk format revision history
  * !!! always update this for every incompatible change !!!
@@ -317,6 +317,8 @@ struct sb {
 	struct rw_semaphore delta_lock; /* delta transition exclusive */
 	unsigned blocksize, blockbits, blockmask;
 	block_t volblocks, freeblocks, nextalloc;
+	unsigned credits;	/* Blocks reserved for inflight operations */
+	int margin;	/* ENOSPC when freeblocks less than this */
 	unsigned entries_per_node; /* must be per-btree type, get rid of this */
 	unsigned max_inodes_per_block; /* get rid of this and use entries per leaf */
 	unsigned version;	/* Currently mounted volume version view */
@@ -881,14 +883,21 @@ int retire_frees(struct sb *sb, struct s
 int retire_frees(struct sb *sb, struct stash *defree);
 void destroy_defree(struct stash *defree);
 
-/* commit.c */
+/* utility.c */
 int vecio(int rw, struct block_device *dev, sector_t sector,
 	bio_end_io_t endio, void *data, unsigned vecs, struct bio_vec *vec);
 int syncio(int rw, struct block_device *dev, sector_t sector, unsigned vecs, struct bio_vec *vec);
 int devio(int rw, struct block_device *dev, loff_t offset, void *data, unsigned len);
+
+/* commit.c */
+
 int load_sb(struct sb *sb);
 int save_sb(struct sb *sb);
 int load_itable(struct sb *sb);
+int reserve_credits(struct sb *sb, unsigned credits);
+int change_begin(struct sb *sb);
+int reduce_begin(struct sb *sb);
+int change_end(struct sb *sb);
 
 /* temporary hack for buffer */
 struct buffer_head *blockread(struct address_space *mapping, block_t iblock);
@@ -916,9 +925,6 @@ static inline struct buffer_head *blockd
 	return buffer;
 }
 
-static inline void change_begin(struct sb *sb) { }
-static inline void change_end(struct sb *sb) { }
-
 #endif /* __KERNEL__ */
 
 static inline struct buffer_head *vol_getblk(struct sb *sb, block_t block)
diff -r fbdd7c18a67c user/super.c
--- a/user/super.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/super.c	Mon Mar 02 17:32:32 2009 -0800
@@ -13,13 +13,6 @@
 #ifndef trace
 #define trace trace_on
 #endif
-
-int devio(int rw, struct dev *dev, loff_t offset, void *data, unsigned len)
-{
-	return ioabs(dev->fd, data, len, rw, offset);
-}
-
-#include "kernel/commit.c"
 
 int sync_super(struct sb *sb)
 {
diff -r fbdd7c18a67c user/tux3.c
--- a/user/tux3.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/tux3.c	Mon Mar 02 17:32:32 2009 -0800
@@ -11,8 +11,8 @@
 #include "inode.c"
 #include <getopt.h>
 
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 int fls(uint32_t v)
 {
diff -r fbdd7c18a67c user/tux3.h
--- a/user/tux3.h	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/tux3.h	Mon Mar 02 17:32:32 2009 -0800
@@ -212,9 +212,6 @@ static inline dev_t huge_decode_dev(u64 
 
 #define mark_btree_dirty(x) do {} while (0)
 
-void change_begin(struct sb *sb);
-void change_end(struct sb *sb);
-
 #define INIT_INODE(inode, sb, mode)			\
 	.i_sb = sb,					\
 	.i_mode = mode,					\
@@ -267,4 +264,7 @@ static inline void mark_inode_dirty(stru
 
 enum rw { READ, WRITE };
 
+int change_begin(struct sb *sb);
+int change_end(struct sb *sb);
+
 #endif
diff -r fbdd7c18a67c user/tux3fuse.c
--- a/user/tux3fuse.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/tux3fuse.c	Mon Mar 02 17:32:32 2009 -0800
@@ -48,8 +48,8 @@
 #undef trace
 #define trace trace_on
 
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 static struct sb *sb;
 static struct dev *dev;
diff -r fbdd7c18a67c user/tux3graph.c
--- a/user/tux3graph.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/tux3graph.c	Mon Mar 02 17:32:32 2009 -0800
@@ -13,8 +13,8 @@
 #include "inode.c"
 #include <getopt.h>
 
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 static const char *dtree_names[] = {
 	[TUX_BITMAP_INO]	= "bitmap",
diff -r fbdd7c18a67c user/xattr.c
--- a/user/xattr.c	Sun Mar 01 11:11:01 2009 +0900
+++ b/user/xattr.c	Mon Mar 02 17:32:32 2009 -0800
@@ -21,8 +21,8 @@
 #include "kernel/xattr.c"
 #include "kernel/ileaf.c"
 
-void change_begin(struct sb *sb) { }
-void change_end(struct sb *sb) { }
+int change_begin(struct sb *sb) { return 0; }
+int change_end(struct sb *sb) { return 0; }
 
 int main(int argc, char *argv[])
 {
_______________________________________________
Tux3 mailing list
Tux3@tux3.org
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3

Reply via email to