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
[email protected]
http://mailman.tux3.org/cgi-bin/mailman/listinfo/tux3