Re: [Cluster-devel] [PATCH] fs: record task name which froze superblock

2015-02-17 Thread Alexey Dobriyan
On Mon, Feb 16, 2015 at 10:38:52AM +0100, Jan Kara wrote:
 On Sat 14-02-15 21:55:24, Alexey Dobriyan wrote:
  Freezing and thawing are separate system calls, task which is supposed
  to thaw filesystem/superblock can disappear due to crash or not thaw
  due to a bug. Record at least task name (we can't take task_struct
  reference) to make support engineer's life easier.
  
  Hopefully 16 bytes per superblock isn't much.
  
  P.S.: Cc'ing GFS2 people just in case they want to correct
  my understanding of GFS2 having async freeze code.
  
  Signed-off-by: Alexey Dobriyan adobri...@gmail.com
   Hum, and when do you show the task name? Or do you expect that customer
 takes a crashdump and support just finds it in memory?

Yeah, having at least something in crashdump is fine.

  --- a/fs/ioctl.c
  +++ b/fs/ioctl.c
  @@ -518,6 +518,7 @@ static int ioctl_fioasync(unsigned int fd, struct file 
  *filp,
   static int ioctl_fsfreeze(struct file *filp)
   {
  struct super_block *sb = file_inode(filp)-i_sb;
  +   int rv;
   
  if (!capable(CAP_SYS_ADMIN))
  return -EPERM;
  @@ -527,22 +528,31 @@ static int ioctl_fsfreeze(struct file *filp)
  return -EOPNOTSUPP;
   
  /* Freeze */
  -   if (sb-s_op-freeze_super)
  -   return sb-s_op-freeze_super(sb);
  -   return freeze_super(sb);
  +   if (sb-s_op-freeze_super) {
  +   rv = sb-s_op-freeze_super(sb);
  +   if (rv == 0)
  +   get_task_comm(sb-s_writers.freeze_comm, current);
  +   } else
  +   rv = freeze_super(sb);
  +   return rv;
   Why don't you just set the name in ioctl_fsfreeze() in both cases?

There are users of freeze_super() in GFS2 unless I'm misreading code.

 Also you seem to be missing freezing / thawing in freeze/thaw_bdev()
 functions.

You are correct. Resending patch (blockdev freezing tested with XFS).

  --- a/include/linux/fs.h
  +++ b/include/linux/fs.h
  @@ -1221,6 +1221,8 @@ struct sb_writers {
  int frozen; /* Is sb frozen? */
  wait_queue_head_t   wait_unfrozen;  /* queue for waiting for
 sb to be thawed */
  +   /* who froze superblock */
  +   charfreeze_comm[16];
   Here should be TASK_COMM_LEN, shouldn't it?

It will pull sched.h, dunno if we care about headers anymore.

Alexey



[Cluster-devel] [PATCH v2] fs: record task name which froze superblock

2015-02-17 Thread Alexey Dobriyan
Freezing and thawing are separate system calls, task which is supposed
to thaw filesystem/superblock can disappear due to crash or not thaw
due to a bug. Record at least task name (we can't take task_struct
reference) to make support engineer's life easier.

Hopefully 16 bytes per superblock isn't much.

Signed-off-by: Alexey Dobriyan adobri...@gmail.com
---

 fs/block_dev.c |   12 
 fs/ioctl.c |   22 --
 fs/super.c |2 ++
 include/linux/fs.h |2 ++
 4 files changed, 28 insertions(+), 10 deletions(-)

--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -227,9 +227,11 @@ struct super_block *freeze_bdev(struct block_device *bdev)
sb = get_active_super(bdev);
if (!sb)
goto out;
-   if (sb-s_op-freeze_super)
+   if (sb-s_op-freeze_super) {
error = sb-s_op-freeze_super(sb);
-   else
+   if (error == 0)
+   get_task_comm(sb-s_writers.freeze_comm, current);
+   } else
error = freeze_super(sb);
if (error) {
deactivate_super(sb);
@@ -267,9 +269,11 @@ int thaw_bdev(struct block_device *bdev, struct 
super_block *sb)
if (!sb)
goto out;
 
-   if (sb-s_op-thaw_super)
+   if (sb-s_op-thaw_super) {
error = sb-s_op-thaw_super(sb);
-   else
+   if (error == 0)
+   memset(sb-s_writers.freeze_comm, 0, TASK_COMM_LEN);
+   } else
error = thaw_super(sb);
if (error) {
bdev-bd_fsfreeze_count++;
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -518,6 +518,7 @@ static int ioctl_fioasync(unsigned int fd, struct file 
*filp,
 static int ioctl_fsfreeze(struct file *filp)
 {
struct super_block *sb = file_inode(filp)-i_sb;
+   int rv;
 
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
@@ -527,22 +528,31 @@ static int ioctl_fsfreeze(struct file *filp)
return -EOPNOTSUPP;
 
/* Freeze */
-   if (sb-s_op-freeze_super)
-   return sb-s_op-freeze_super(sb);
-   return freeze_super(sb);
+   if (sb-s_op-freeze_super) {
+   rv = sb-s_op-freeze_super(sb);
+   if (rv == 0)
+   get_task_comm(sb-s_writers.freeze_comm, current);
+   } else
+   rv = freeze_super(sb);
+   return rv;
 }
 
 static int ioctl_fsthaw(struct file *filp)
 {
struct super_block *sb = file_inode(filp)-i_sb;
+   int rv;
 
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
 
/* Thaw */
-   if (sb-s_op-thaw_super)
-   return sb-s_op-thaw_super(sb);
-   return thaw_super(sb);
+   if (sb-s_op-thaw_super) {
+   rv = sb-s_op-thaw_super(sb);
+   if (rv == 0)
+   memset(sb-s_writers.freeze_comm, 0, TASK_COMM_LEN);
+   } else
+   rv = thaw_super(sb);
+   return rv;
 }
 
 /*
--- a/fs/super.c
+++ b/fs/super.c
@@ -1355,6 +1355,7 @@ int freeze_super(struct super_block *sb)
 * sees write activity when frozen is set to SB_FREEZE_COMPLETE.
 */
sb-s_writers.frozen = SB_FREEZE_COMPLETE;
+   get_task_comm(sb-s_writers.freeze_comm, current);
up_write(sb-s_umount);
return 0;
 }
@@ -1391,6 +1392,7 @@ int thaw_super(struct super_block *sb)
 
 out:
sb-s_writers.frozen = SB_UNFROZEN;
+   memset(sb-s_writers.freeze_comm, 0, TASK_COMM_LEN);
smp_wmb();
wake_up(sb-s_writers.wait_unfrozen);
deactivate_locked_super(sb);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1221,6 +1221,8 @@ struct sb_writers {
int frozen; /* Is sb frozen? */
wait_queue_head_t   wait_unfrozen;  /* queue for waiting for
   sb to be thawed */
+   /* who froze superblock and forgot to thaw it */
+   charfreeze_comm[16];
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map  lock_map[SB_FREEZE_LEVELS];
 #endif



[Cluster-devel] [GFS2 PATCH] GFS2: Allocate reservation during write_begin if needed

2015-02-17 Thread Bob Peterson
Hi,

This patch adds a call to function gfs2_rs_alloc to make sure a
reservation structure has been allocated before attempting to
reserve blocks.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson rpete...@redhat.com 
---
 fs/gfs2/aops.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 805b37f..6453e23 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -675,6 +675,9 @@ static int gfs2_write_begin(struct file *file, struct 
address_space *mapping,
if (error)
goto out_unlock;
 
+   error = gfs2_rs_alloc(ip);
+   if (error)
+   goto out_qunlock;
requested = data_blocks + ind_blocks;
ap.target = requested;
error = gfs2_inplace_reserve(ip, ap);



Re: [Cluster-devel] [GFS2 PATCH 1/3] gfs2: perform quota checks against allocation parameters

2015-02-17 Thread Abhijith Das


- Original Message -
 From: Steven Whitehouse swhit...@redhat.com
 To: Abhi Das a...@redhat.com, cluster-devel@redhat.com
 Sent: Tuesday, February 17, 2015 3:38:07 AM
 Subject: Re: [Cluster-devel] [GFS2 PATCH 1/3] gfs2: perform quota checks 
 against allocation parameters
 
 Hi,
 
 On 16/02/15 17:59, Abhi Das wrote:
  Use struct gfs2_alloc_parms as an argument to gfs2_quota_check()
  and gfs2_quota_lock_check() to check for quota violations while
  accounting for the new blocks requested by the current operation
  in ap-target.
 
  Previously, the number of new blocks requested during an operation
  were not accounted for during quota_check and would allow these
  operations to exceed quota. This was not very apparent since most
  operations allocated only 1 block at a time and quotas would get
  violated in the next operation. i.e. quota excess would only be by
  1 block or so. With fallocate, (where we allocate a bunch of blocks
  at once) the quota excess is non-trivial and is addressed by this
  patch.
 
  Resolves: rhbz#1174295
  Signed-off-by: Abhi Das a...@redhat.com
  ---
fs/gfs2/aops.c   |  6 +++---
fs/gfs2/bmap.c   |  2 +-
fs/gfs2/file.c   |  9 +
fs/gfs2/incore.h |  2 +-
fs/gfs2/inode.c  | 18 ++
fs/gfs2/quota.c  |  6 +++---
fs/gfs2/quota.h  |  8 +---
fs/gfs2/xattr.c  |  2 +-
8 files changed, 29 insertions(+), 24 deletions(-)
 
  diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
  index 805b37f..0261126 100644
  --- a/fs/gfs2/aops.c
  +++ b/fs/gfs2/aops.c
  @@ -671,12 +671,12 @@ static int gfs2_write_begin(struct file *file, struct
  address_space *mapping,

  if (alloc_required) {
  struct gfs2_alloc_parms ap = { .aflags = 0, };
  -   error = gfs2_quota_lock_check(ip);
  +   requested = data_blocks + ind_blocks;
  +   ap.target = requested;
  +   error = gfs2_quota_lock_check(ip, ap);
  if (error)
  goto out_unlock;

  -   requested = data_blocks + ind_blocks;
  -   ap.target = requested;
  error = gfs2_inplace_reserve(ip, ap);
  if (error)
  goto out_qunlock;
  diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
  index f0b945a..61296ec 100644
  --- a/fs/gfs2/bmap.c
  +++ b/fs/gfs2/bmap.c
  @@ -1224,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)

  if (gfs2_is_stuffed(ip) 
  (size  (sdp-sd_sb.sb_bsize - sizeof(struct gfs2_dinode {
  -   error = gfs2_quota_lock_check(ip);
  +   error = gfs2_quota_lock_check(ip, ap);
  if (error)
  return error;

  diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
  index 6e600ab..2ea420a 100644
  --- a/fs/gfs2/file.c
  +++ b/fs/gfs2/file.c
  @@ -429,11 +429,11 @@ static int gfs2_page_mkwrite(struct vm_area_struct
  *vma, struct vm_fault *vmf)
  if (ret)
  goto out_unlock;

  -   ret = gfs2_quota_lock_check(ip);
  -   if (ret)
  -   goto out_unlock;
  gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, data_blocks, ind_blocks);
  ap.target = data_blocks + ind_blocks;
  +   ret = gfs2_quota_lock_check(ip, ap);
  +   if (ret)
  +   goto out_unlock;
  ret = gfs2_inplace_reserve(ip, ap);
  if (ret)
  goto out_quota_unlock;
  @@ -828,7 +828,8 @@ static long __gfs2_fallocate(struct file *file, int
  mode, loff_t offset, loff_t
  offset += bytes;
  continue;
  }
  -   error = gfs2_quota_lock_check(ip);
  +   ap.target = bytes  sdp-sd_sb.sb_bsize_shift;
  +   error = gfs2_quota_lock_check(ip, ap);
  if (error)
  return error;
retry:
  diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
  index 7a2dbbc..3a4ea50 100644
  --- a/fs/gfs2/incore.h
  +++ b/fs/gfs2/incore.h
  @@ -301,7 +301,7 @@ struct gfs2_blkreserv {
 * to the allocation code.
 */
struct gfs2_alloc_parms {
  -   u32 target;
  +   u64 target;
 Why does this need to be 64 bits in size? The max size of an rgrp is
 2^32, so there should be no need to represent an extent larger than that,
 
 Steve.
 

This has got to do with setattr_chown() which calls gfs2_get_inode_blocks() to
get the number of blocks used by the inode being chowned. This is a u64 value
and since we also use ap.target to check against quotas in gfs2_quota_check(),
I had to change its size.

Cheers!
--Abhi



Re: [Cluster-devel] [GFS2 PATCH 3/3] gfs2: allow fallocate to max out quotas/fs efficiently

2015-02-17 Thread Abhijith Das


- Original Message -
 From: Steven Whitehouse swhit...@redhat.com
 To: Abhi Das a...@redhat.com, cluster-devel@redhat.com
 Sent: Tuesday, February 17, 2015 3:41:15 AM
 Subject: Re: [Cluster-devel] [GFS2 PATCH 3/3] gfs2: allow fallocate to max 
 out quotas/fs efficiently
 
 Hi,
 
 On 16/02/15 17:59, Abhi Das wrote:
  We can quickly get an estimate of how many more blocks are
  available for allocation restricted by quota and fs size
  respectively using the ap-allowed field in the gfs2_alloc_parms
  structure. gfs2_quota_check() and gfs2_inplace_reserve() provide
  these values.
 
  By re-trying to allocate what's available instead of guessing, we
  can max out quotas or the filesystem efficiently.
 
  Bear in mind that this applies only when the requested fallocate
  operation would otherwise error out with -EDQUOT or -ENOSPC without
  utilizing all the blocks that might still be available.
 
  Signed-off-by: Abhi Das a...@redhat.com
  ---
fs/gfs2/file.c | 18 +++---
1 file changed, 11 insertions(+), 7 deletions(-)
 
  diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
  index 2ea420a..57129fa 100644
  --- a/fs/gfs2/file.c
  +++ b/fs/gfs2/file.c
  @@ -829,20 +829,24 @@ static long __gfs2_fallocate(struct file *file, int
  mode, loff_t offset, loff_t
  continue;
  }
  ap.target = bytes  sdp-sd_sb.sb_bsize_shift;
  +   quota_retry:
  error = gfs2_quota_lock_check(ip, ap);
  -   if (error)
  +   if (error) {
  +   if (error == -EDQUOT  ap.allowed) {
  +   bytes = ap.allowed  sdp-sd_sb.sb_bsize_shift;
  +   ap.target = ap.allowed;
  +   goto quota_retry;
  +   }
  return error;
 Do you really need to loop here if -EDQUOT is returned and ap.allowed is
 set? Why not just continue after having updated the target value?
 
 Otherwise I think these patches look good,
 
 Steve.
 

If gfs2_quota_lock_check() fails, the quota isn't locked, which we'd have to do
anyway. And I figured there's a race here where some other process could use up
all or part of ap.allowed blocks before we re-lock the quota thereby causing us
to exceed quotas. So, I decided to retry gfs2_quota_lock_check() itself.

Cheers!
--Abhi



Re: [Cluster-devel] [GFS2 PATCH] GFS2: Allocate reservation during write_begin if needed

2015-02-17 Thread Bob Peterson
- Original Message -
 Hi,
 
 
 Since we set the allocation structure when the write call begins, and it
 is not deallocated until there are no writers left with the file open,
 how does this happen?
 
 Steve.

Hi,

In a normal write, the code goes through gfs2_page_mkwrite or
gfs2_file_aio_write. In the failing scenario, it's going through
sendfile. I suppose I could patch sendfile as an alternative, but
the advantage here is that this patch will do it only if a block
allocation is needed.

Regards,

Bob Peterson
Red Hat File Systems



Re: [Cluster-devel] [GFS2 PATCH] GFS2: Allocate reservation during write_begin if needed

2015-02-17 Thread Steven Whitehouse

Hi,


Since we set the allocation structure when the write call begins, and it 
is not deallocated until there are no writers left with the file open, 
how does this happen?


Steve.

On 17/02/15 17:09, Bob Peterson wrote:

Hi,

This patch adds a call to function gfs2_rs_alloc to make sure a
reservation structure has been allocated before attempting to
reserve blocks.

Regards,

Bob Peterson
Red Hat File Systems

Signed-off-by: Bob Peterson rpete...@redhat.com
---
  fs/gfs2/aops.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 805b37f..6453e23 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -675,6 +675,9 @@ static int gfs2_write_begin(struct file *file, struct 
address_space *mapping,
if (error)
goto out_unlock;
  
+		error = gfs2_rs_alloc(ip);

+   if (error)
+   goto out_qunlock;
requested = data_blocks + ind_blocks;
ap.target = requested;
error = gfs2_inplace_reserve(ip, ap);





Re: [Cluster-devel] [GFS2 PATCH] GFS2: Allocate reservation during write_begin if needed

2015-02-17 Thread Steven Whitehouse

Hi,

On 17/02/15 19:09, Bob Peterson wrote:

- Original Message -

Hi,


Since we set the allocation structure when the write call begins, and it
is not deallocated until there are no writers left with the file open,
how does this happen?

Steve.

Hi,

In a normal write, the code goes through gfs2_page_mkwrite or
gfs2_file_aio_write. In the failing scenario, it's going through
sendfile. I suppose I could patch sendfile as an alternative, but
the advantage here is that this patch will do it only if a block
allocation is needed.

Regards,

Bob Peterson
Red Hat File Systems


Ah, I see. In which case that code path should be patched. So it should 
be part of the splice code I think, since it should be done at the 
higher level, and not at the write_begin level, since that is too late. 
We should have a call to the reservation code too at that point, to 
ensure that we don't have fragmentation issues. So we need a wrapper for 
|iter_file_splice_write| along the lines of gfs2_file_write_iter I think,


Steve.



Re: [Cluster-devel] [PATCH] Add myself (Bob Peterson) as a maintainer of GFS2

2015-02-17 Thread Bob Peterson
- Original Message -
 Hi Bob,
 
 On Mon, 16 Feb 2015 09:20:56 -0500 (EST) Bob Peterson rpete...@redhat.com
 wrote:
 
  This patch adds Bob Peterson as a maintainer of the GFS2 file system.
  It also changes the development repository to a shared location rather
  than Steve Whitehouse's private location.
 
 Please also consider letting the linux-next maintainer know :-)
 
 i.e. does this mean I should change the repo/branch I fetch into
 linux-next each day and should I add you to the contacts?
 --
 Cheers,
 Stephen Rothwells...@canb.auug.org.au
 

Hi Stephen,

Yes, indeed. I was going to let you know as soon as I got things set up.
Unfortunately, I've been pulled in a lot of directions lately.

I've set up a for-next branch from which you can do your daily fetch:
pub/scm/linux/kernel/git/gfs2/linux-gfs2.git

Currently it's empty, and yes, please add me to the contacts.

Regards,

Bob Peterson
Red Hat File Systems



Re: [Cluster-devel] [GFS2 PATCH 1/3] gfs2: perform quota checks against allocation parameters

2015-02-17 Thread Steven Whitehouse

Hi,

On 16/02/15 17:59, Abhi Das wrote:

Use struct gfs2_alloc_parms as an argument to gfs2_quota_check()
and gfs2_quota_lock_check() to check for quota violations while
accounting for the new blocks requested by the current operation
in ap-target.

Previously, the number of new blocks requested during an operation
were not accounted for during quota_check and would allow these
operations to exceed quota. This was not very apparent since most
operations allocated only 1 block at a time and quotas would get
violated in the next operation. i.e. quota excess would only be by
1 block or so. With fallocate, (where we allocate a bunch of blocks
at once) the quota excess is non-trivial and is addressed by this
patch.

Resolves: rhbz#1174295
Signed-off-by: Abhi Das a...@redhat.com
---
  fs/gfs2/aops.c   |  6 +++---
  fs/gfs2/bmap.c   |  2 +-
  fs/gfs2/file.c   |  9 +
  fs/gfs2/incore.h |  2 +-
  fs/gfs2/inode.c  | 18 ++
  fs/gfs2/quota.c  |  6 +++---
  fs/gfs2/quota.h  |  8 +---
  fs/gfs2/xattr.c  |  2 +-
  8 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 805b37f..0261126 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -671,12 +671,12 @@ static int gfs2_write_begin(struct file *file, struct 
address_space *mapping,
  
  	if (alloc_required) {

struct gfs2_alloc_parms ap = { .aflags = 0, };
-   error = gfs2_quota_lock_check(ip);
+   requested = data_blocks + ind_blocks;
+   ap.target = requested;
+   error = gfs2_quota_lock_check(ip, ap);
if (error)
goto out_unlock;
  
-		requested = data_blocks + ind_blocks;

-   ap.target = requested;
error = gfs2_inplace_reserve(ip, ap);
if (error)
goto out_qunlock;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index f0b945a..61296ec 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1224,7 +1224,7 @@ static int do_grow(struct inode *inode, u64 size)
  
  	if (gfs2_is_stuffed(ip) 

(size  (sdp-sd_sb.sb_bsize - sizeof(struct gfs2_dinode {
-   error = gfs2_quota_lock_check(ip);
+   error = gfs2_quota_lock_check(ip, ap);
if (error)
return error;
  
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c

index 6e600ab..2ea420a 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -429,11 +429,11 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, 
struct vm_fault *vmf)
if (ret)
goto out_unlock;
  
-	ret = gfs2_quota_lock_check(ip);

-   if (ret)
-   goto out_unlock;
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, data_blocks, ind_blocks);
ap.target = data_blocks + ind_blocks;
+   ret = gfs2_quota_lock_check(ip, ap);
+   if (ret)
+   goto out_unlock;
ret = gfs2_inplace_reserve(ip, ap);
if (ret)
goto out_quota_unlock;
@@ -828,7 +828,8 @@ static long __gfs2_fallocate(struct file *file, int mode, 
loff_t offset, loff_t
offset += bytes;
continue;
}
-   error = gfs2_quota_lock_check(ip);
+   ap.target = bytes  sdp-sd_sb.sb_bsize_shift;
+   error = gfs2_quota_lock_check(ip, ap);
if (error)
return error;
  retry:
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 7a2dbbc..3a4ea50 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -301,7 +301,7 @@ struct gfs2_blkreserv {
   * to the allocation code.
   */
  struct gfs2_alloc_parms {
-   u32 target;
+   u64 target;
Why does this need to be 64 bits in size? The max size of an rgrp is 
2^32, so there should be no need to represent an extent larger than that,


Steve.


u32 aflags;
  };
  
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c

index 73c72253..08bc84d 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -382,7 +382,7 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, 
unsigned *dblocks)
struct gfs2_alloc_parms ap = { .target = *dblocks, .aflags = flags, };
int error;
  
-	error = gfs2_quota_lock_check(ip);

+   error = gfs2_quota_lock_check(ip, ap);
if (error)
goto out;
  
@@ -525,7 +525,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name,

int error;
  
  	if (da-nr_blocks) {

-   error = gfs2_quota_lock_check(dip);
+   error = gfs2_quota_lock_check(dip, ap);
if (error)
goto fail_quota_locks;
  
@@ -953,7 +953,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir,
  
  	if (da.nr_blocks) {

struct gfs2_alloc_parms ap = { .target = da.nr_blocks, };
-   error = gfs2_quota_lock_check(dip);
+   error = gfs2_quota_lock_check(dip, ap);

Re: [Cluster-devel] [GFS2 PATCH 3/3] gfs2: allow fallocate to max out quotas/fs efficiently

2015-02-17 Thread Steven Whitehouse

Hi,

On 16/02/15 17:59, Abhi Das wrote:

We can quickly get an estimate of how many more blocks are
available for allocation restricted by quota and fs size
respectively using the ap-allowed field in the gfs2_alloc_parms
structure. gfs2_quota_check() and gfs2_inplace_reserve() provide
these values.

By re-trying to allocate what's available instead of guessing, we
can max out quotas or the filesystem efficiently.

Bear in mind that this applies only when the requested fallocate
operation would otherwise error out with -EDQUOT or -ENOSPC without
utilizing all the blocks that might still be available.

Signed-off-by: Abhi Das a...@redhat.com
---
  fs/gfs2/file.c | 18 +++---
  1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 2ea420a..57129fa 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -829,20 +829,24 @@ static long __gfs2_fallocate(struct file *file, int mode, 
loff_t offset, loff_t
continue;
}
ap.target = bytes  sdp-sd_sb.sb_bsize_shift;
+   quota_retry:
error = gfs2_quota_lock_check(ip, ap);
-   if (error)
+   if (error) {
+   if (error == -EDQUOT  ap.allowed) {
+   bytes = ap.allowed  sdp-sd_sb.sb_bsize_shift;
+   ap.target = ap.allowed;
+   goto quota_retry;
+   }
return error;
Do you really need to loop here if -EDQUOT is returned and ap.allowed is 
set? Why not just continue after having updated the target value?


Otherwise I think these patches look good,

Steve.


-retry:
+   }
+   retry:
gfs2_write_calc_reserv(ip, bytes, data_blocks, ind_blocks);
  
  		ap.target = data_blocks + ind_blocks;

error = gfs2_inplace_reserve(ip, ap);
if (error) {
-   if (error == -ENOSPC  bytes  sdp-sd_sb.sb_bsize) {
-   bytes = 1;
-   bytes = bsize_mask;
-   if (bytes == 0)
-   bytes = sdp-sd_sb.sb_bsize;
+   if (error == -ENOSPC  ap.allowed) {
+   bytes = ap.allowed  sdp-sd_sb.sb_bsize_shift;
goto retry;
}
goto out_qunlock;