[PATCH] fat: Editions to support fat_fallocate()

2007-12-22 Thread Steven Cavanagh
From: Steven Cavanagh <[EMAIL PROTECTED]>

Added support for fallocate for a msdos fat driver. This allows
preallocation of clusters to an inode before writes to reduce
file fragmentation

Signed-off-by: Steven.Cavanagh <[EMAIL PROTECTED]>
---

 fs/fat/file.c |   45 +
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..f753c6a 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -15,6 +15,7 @@ #include 
 #include 
 #include 
 #include 
+#include 
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
  unsigned int cmd, unsigned long arg)
@@ -312,8 +313,52 @@ int fat_getattr(struct vfsmount *mnt, st
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
+/*
+ * preallocate space for a file. This implements fat fallocate inode
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset.
+ */
+long fat_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+   int ret = 0;
+   loff_t filesize = inode->i_size;
+
+   /* preallocation to directories is currently not supported */
+   if (S_ISDIR(inode->i_mode)) {
+   printk(KERN_ERR
+   "fat_fallocate(): Directory prealloc not supported\n");
+   return -ENODEV;
+   }
+
+   if ((offset + len) <= MSDOS_I(inode)->mmu_private) {
+   printk(KERN_INFO
+   "fat_fallocate():Blocks already allocated\n");
+   return 0;
+   }
+
+   if ((offset + len) > MSDOS_I(inode)->mmu_private) {
+
+   mutex_lock(>i_mutex);
+   ret = fat_cont_expand(inode, (offset + len));
+   if (ret) {
+   printk(KERN_ERR
+   "fat_fallocate():fat_cont_expand() error\n");
+   mutex_unlock(>i_mutex);
+   return ret;
+   }
+   mutex_unlock(>i_mutex);
+   }
+   if (mode & FALLOC_FL_KEEP_SIZE) {
+   mutex_lock(>i_mutex);
+   i_size_write(inode, filesize);
+   mutex_unlock(>i_mutex);
+   }
+   return ret;
+}
+
 const struct inode_operations fat_file_inode_operations = {
.truncate   = fat_truncate,
.setattr= fat_notify_change,
.getattr= fat_getattr,
+   .fallocate  = fat_fallocate,
 };
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] fat: Editions to support fat_fallocate()

2007-12-22 Thread Steven Cavanagh
From: Steven Cavanagh [EMAIL PROTECTED]

Added support for fallocate for a msdos fat driver. This allows
preallocation of clusters to an inode before writes to reduce
file fragmentation

Signed-off-by: Steven.Cavanagh [EMAIL PROTECTED]
---

 fs/fat/file.c |   45 +
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..f753c6a 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -15,6 +15,7 @@ #include linux/buffer_head.h
 #include linux/writeback.h
 #include linux/backing-dev.h
 #include linux/blkdev.h
+#include linux/falloc.h
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
  unsigned int cmd, unsigned long arg)
@@ -312,8 +313,52 @@ int fat_getattr(struct vfsmount *mnt, st
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
+/*
+ * preallocate space for a file. This implements fat fallocate inode
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset.
+ */
+long fat_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+   int ret = 0;
+   loff_t filesize = inode-i_size;
+
+   /* preallocation to directories is currently not supported */
+   if (S_ISDIR(inode-i_mode)) {
+   printk(KERN_ERR
+   fat_fallocate(): Directory prealloc not supported\n);
+   return -ENODEV;
+   }
+
+   if ((offset + len) = MSDOS_I(inode)-mmu_private) {
+   printk(KERN_INFO
+   fat_fallocate():Blocks already allocated\n);
+   return 0;
+   }
+
+   if ((offset + len)  MSDOS_I(inode)-mmu_private) {
+
+   mutex_lock(inode-i_mutex);
+   ret = fat_cont_expand(inode, (offset + len));
+   if (ret) {
+   printk(KERN_ERR
+   fat_fallocate():fat_cont_expand() error\n);
+   mutex_unlock(inode-i_mutex);
+   return ret;
+   }
+   mutex_unlock(inode-i_mutex);
+   }
+   if (mode  FALLOC_FL_KEEP_SIZE) {
+   mutex_lock(inode-i_mutex);
+   i_size_write(inode, filesize);
+   mutex_unlock(inode-i_mutex);
+   }
+   return ret;
+}
+
 const struct inode_operations fat_file_inode_operations = {
.truncate   = fat_truncate,
.setattr= fat_notify_change,
.getattr= fat_getattr,
+   .fallocate  = fat_fallocate,
 };
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] fat: Editions to support fat_fallocate()

2007-12-11 Thread Steven Cavanagh
From: Steven Cavanagh <[EMAIL PROTECTED]>

Added support for fallocate for a msdos fat driver. This allows
preallocation of clusters to an inode before writes to reduce
file fragmentation

Signed-off-by: Steven.Cavanagh <[EMAIL PROTECTED]>
---

 fs/fat/cache.c   |9 ++
 fs/fat/file.c|  167 ++
 fs/fat/inode.c   |   21 ++
 include/linux/msdos_fs.h |5 +
 4 files changed, 201 insertions(+), 1 deletions(-)

diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 639b3b4..1a69ce4 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -8,6 +8,8 @@
  *  May 1999. AV. Fixed the bogosity with FAT32 (read "FAT28"). Fscking lusers.
  */
 
+#undef DEBUG
+
 #include 
 #include 
 #include 
@@ -316,6 +318,10 @@ int fat_bmap(struct inode *inode, sector
 
cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits);
offset  = sector & (sbi->sec_per_clus - 1);
+
+   pr_debug("fat_bmap():cluster:%d, offset:%d, last_block:%llu\n",
+   cluster, offset, last_block);
+
cluster = fat_bmap_cluster(inode, cluster);
if (cluster < 0)
return cluster;
@@ -324,6 +330,9 @@ int fat_bmap(struct inode *inode, sector
*mapped_blocks = sbi->sec_per_clus - offset;
if (*mapped_blocks > last_block - sector)
*mapped_blocks = last_block - sector;
+
+   pr_debug("fat_bmap():cluster:%d, phys:%llu\n",
+   cluster, *phys);
}
return 0;
 }
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..9698d42 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -6,6 +6,8 @@
  *  regular file handling primitives for fat-based filesystems
  */
 
+#undef DEBUG
+
 #include 
 #include 
 #include 
@@ -15,6 +17,7 @@ #include 
 #include 
 #include 
 #include 
+#include 
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
  unsigned int cmd, unsigned long arg)
@@ -312,8 +315,172 @@ int fat_getattr(struct vfsmount *mnt, st
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
+/*
+ * preallocate space for a file. This implements fat fallocate inode
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset.
+ */
+long fat_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+   unsigned int blkbits = inode->i_blkbits;
+   int ret = 0, err;
+   unsigned long offset_block, new_blocks;
+   unsigned long max_blocks, nblocks = 0;
+   unsigned long mapped_blocks = 0, cluster_offset = 0;
+
+   struct buffer_head bh;
+
+   loff_t newsize = 0;
+
+   struct super_block *sb = inode->i_sb;
+   struct msdos_sb_info *sbi = MSDOS_SB(sb);
+   sector_t phys;
+   struct timespec now;
+
+   /* preallocation to directories is currently not supported */
+   if (S_ISDIR(inode->i_mode)) {
+   printk(KERN_ERR
+   "fat_fallocate(): Directory prealloc not supported\n");
+   return -ENODEV;
+   }
+
+   offset_block = offset >> blkbits;
+   pr_debug("fat_fallocate:offset block:%lu\n", offset_block);
+
+   /* Determine new allocation block */
+   new_blocks = (MSDOS_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
+   - offset_block;
+   pr_debug("fat_fallocate:allocate block:%lu\n", new_blocks);
+
+   if ((offset_block + new_blocks) <=
+   (MSDOS_BLOCK_ALIGN(i_size_read(inode), blkbits)
+   >> blkbits)) {
+   printk(KERN_ERR
+   "fat_fallocate():Blocks already allocated\n");
+   return -EIO;
+   }
+   if (offset_block >
+   (MSDOS_BLOCK_ALIGN(i_size_read(inode), blkbits)
+   >> blkbits)) {
+   printk(KERN_ERR
+   "fat_fallocate():Offset error\n");
+   return -EIO;
+   }
+   while (ret >= 0 && nblocks < new_blocks) {
+
+   /* Allocate a new cluster after all the available
+* blocks(sectors) have been allocated.
+*/
+   cluster_offset =
+   (unsigned long)offset_block & (sbi->sec_per_clus - 1);
+   if (!cluster_offset) {
+
+   ret = fat_add_cluster(inode);
+   if (ret) {
+   pr_debug("msdos_fallocate():Add cluster err\
+   inode#%lu, block = %lu, max_blocks = %lu\n",
+   inode->i_ino, offset_block, new_blocks);
+   break;
+   }
+   }
+
+ 

[PATCH] fat: Editions to support fat_fallocate()

2007-12-11 Thread Steven Cavanagh
From: Steven Cavanagh [EMAIL PROTECTED]

Added support for fallocate for a msdos fat driver. This allows
preallocation of clusters to an inode before writes to reduce
file fragmentation

Signed-off-by: Steven.Cavanagh [EMAIL PROTECTED]
---

 fs/fat/cache.c   |9 ++
 fs/fat/file.c|  167 ++
 fs/fat/inode.c   |   21 ++
 include/linux/msdos_fs.h |5 +
 4 files changed, 201 insertions(+), 1 deletions(-)

diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 639b3b4..1a69ce4 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -8,6 +8,8 @@
  *  May 1999. AV. Fixed the bogosity with FAT32 (read FAT28). Fscking lusers.
  */
 
+#undef DEBUG
+
 #include linux/fs.h
 #include linux/msdos_fs.h
 #include linux/buffer_head.h
@@ -316,6 +318,10 @@ int fat_bmap(struct inode *inode, sector
 
cluster = sector  (sbi-cluster_bits - sb-s_blocksize_bits);
offset  = sector  (sbi-sec_per_clus - 1);
+
+   pr_debug(fat_bmap():cluster:%d, offset:%d, last_block:%llu\n,
+   cluster, offset, last_block);
+
cluster = fat_bmap_cluster(inode, cluster);
if (cluster  0)
return cluster;
@@ -324,6 +330,9 @@ int fat_bmap(struct inode *inode, sector
*mapped_blocks = sbi-sec_per_clus - offset;
if (*mapped_blocks  last_block - sector)
*mapped_blocks = last_block - sector;
+
+   pr_debug(fat_bmap():cluster:%d, phys:%llu\n,
+   cluster, *phys);
}
return 0;
 }
diff --git a/fs/fat/file.c b/fs/fat/file.c
index 69a83b5..9698d42 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -6,6 +6,8 @@
  *  regular file handling primitives for fat-based filesystems
  */
 
+#undef DEBUG
+
 #include linux/capability.h
 #include linux/module.h
 #include linux/time.h
@@ -15,6 +17,7 @@ #include linux/buffer_head.h
 #include linux/writeback.h
 #include linux/backing-dev.h
 #include linux/blkdev.h
+#include linux/falloc.h
 
 int fat_generic_ioctl(struct inode *inode, struct file *filp,
  unsigned int cmd, unsigned long arg)
@@ -312,8 +315,172 @@ int fat_getattr(struct vfsmount *mnt, st
 }
 EXPORT_SYMBOL_GPL(fat_getattr);
 
+/*
+ * preallocate space for a file. This implements fat fallocate inode
+ * operation, which gets called from sys_fallocate system call. User
+ * space requests len bytes at offset.
+ */
+long fat_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
+{
+   unsigned int blkbits = inode-i_blkbits;
+   int ret = 0, err;
+   unsigned long offset_block, new_blocks;
+   unsigned long max_blocks, nblocks = 0;
+   unsigned long mapped_blocks = 0, cluster_offset = 0;
+
+   struct buffer_head bh;
+
+   loff_t newsize = 0;
+
+   struct super_block *sb = inode-i_sb;
+   struct msdos_sb_info *sbi = MSDOS_SB(sb);
+   sector_t phys;
+   struct timespec now;
+
+   /* preallocation to directories is currently not supported */
+   if (S_ISDIR(inode-i_mode)) {
+   printk(KERN_ERR
+   fat_fallocate(): Directory prealloc not supported\n);
+   return -ENODEV;
+   }
+
+   offset_block = offset  blkbits;
+   pr_debug(fat_fallocate:offset block:%lu\n, offset_block);
+
+   /* Determine new allocation block */
+   new_blocks = (MSDOS_BLOCK_ALIGN(len + offset, blkbits)  blkbits)
+   - offset_block;
+   pr_debug(fat_fallocate:allocate block:%lu\n, new_blocks);
+
+   if ((offset_block + new_blocks) =
+   (MSDOS_BLOCK_ALIGN(i_size_read(inode), blkbits)
+blkbits)) {
+   printk(KERN_ERR
+   fat_fallocate():Blocks already allocated\n);
+   return -EIO;
+   }
+   if (offset_block 
+   (MSDOS_BLOCK_ALIGN(i_size_read(inode), blkbits)
+blkbits)) {
+   printk(KERN_ERR
+   fat_fallocate():Offset error\n);
+   return -EIO;
+   }
+   while (ret = 0  nblocks  new_blocks) {
+
+   /* Allocate a new cluster after all the available
+* blocks(sectors) have been allocated.
+*/
+   cluster_offset =
+   (unsigned long)offset_block  (sbi-sec_per_clus - 1);
+   if (!cluster_offset) {
+
+   ret = fat_add_cluster(inode);
+   if (ret) {
+   pr_debug(msdos_fallocate():Add cluster err\
+   inode#%lu, block = %lu, max_blocks = %lu\n,
+   inode-i_ino, offset_block, new_blocks);
+   break;
+   }
+   }
+
+   /* mapped blocks = 4 blocks/sector - offset into cluster