From a2e0f79939e09e74698564b88dee709db208e1e2 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 11 Aug 2010 09:53:11 +0100 Subject: GFS2: Remove i_disksize With the update of the truncate code, ip->i_disksize and inode->i_size are merely copies of each other. This means we can remove ip->i_disksize and use inode->i_size exclusively reducing the size of a GFS2 inode by 8 bytes. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 300ada3f21de..15ff4df20aab 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -80,6 +80,19 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip, dent->de_inum.no_addr = cpu_to_be64(ip->i_no_addr); } +static inline int gfs2_check_internal_file_size(struct inode *inode, + u64 minsize, u64 maxsize) +{ + u64 size = i_size_read(inode); + if (size < minsize || size > maxsize) + goto err; + if (size & ((1 << inode->i_blkbits) - 1)) + goto err; + return 0; +err: + gfs2_consist_inode(GFS2_I(inode)); + return -EIO; +} extern void gfs2_set_iop(struct inode *inode); extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, -- cgit v1.2.2 From 3921120e757f9167f3fcd3a1781239824471b14d Mon Sep 17 00:00:00 2001 From: Benjamin Marzinski Date: Fri, 20 Aug 2010 00:21:02 -0500 Subject: GFS2: fallocate support This patch adds support for fallocate to gfs2. Since the gfs2 does not support uninitialized data blocks, it must write out zeros to all the blocks. However, since it does not need to lock any pages to read from, gfs2 can write out the zero blocks much more efficiently. On a moderately full filesystem, fallocate works around 5 times faster on average. The fallocate call also allows gfs2 to add blocks to the file without changing the filesize, which will make it possible for gfs2 to preallocate space for the rindex file, so that gfs2 can grow a completely full filesystem. Signed-off-by: Benjamin Marzinski Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 15ff4df20aab..6720d7d5fbc6 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -19,6 +19,8 @@ extern int gfs2_releasepage(struct page *page, gfp_t gfp_mask); extern int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state, char *buf, loff_t *pos, unsigned size); +extern void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page, + unsigned int from, unsigned int to); extern void gfs2_set_aops(struct inode *inode); static inline int gfs2_is_stuffed(const struct gfs2_inode *ip) -- cgit v1.2.2 From 044b9414c7caf9a26192c73a5b88fa1a8a32a1c1 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Wed, 3 Nov 2010 20:01:07 +0000 Subject: GFS2: Fix inode deallocation race This area of the code has always been a bit delicate due to the subtleties of lock ordering. The problem is that for "normal" alloc/dealloc, we always grab the inode locks first and the rgrp lock later. In order to ensure no races in looking up the unlinked, but still allocated inodes, we need to hold the rgrp lock when we do the lookup, which means that we can't take the inode glock. The solution is to borrow the technique already used by NFS to solve what is essentially the same problem (given an inode number, look up the inode carefully, checking that it really is in the expected state). We cannot do that directly from the allocation code (lock ordering again) so we give the job to the pre-existing delete workqueue and carry on with the allocation as normal. If we find there is no space, we do a journal flush (required anyway if space from a deallocation is to be released) which should block against the pending deallocations, so we should always get the space back. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 6720d7d5fbc6..d8499fadcc53 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -99,7 +99,9 @@ err: extern void gfs2_set_iop(struct inode *inode); extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, u64 no_addr, u64 no_formal_ino); -extern void gfs2_process_unlinked_inode(struct super_block *sb, u64 no_addr); +extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, + u64 *no_formal_ino, + unsigned int blktype); extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); extern int gfs2_inode_refresh(struct gfs2_inode *ip); -- cgit v1.2.2 From b74c79e99389cd79b31fcc08f82c24e492e63c7e Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Fri, 7 Jan 2011 17:49:58 +1100 Subject: fs: provide rcu-walk aware permission i_ops Signed-off-by: Nick Piggin --- fs/gfs2/inode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index d8499fadcc53..732a183efdb3 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -113,7 +113,7 @@ extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, extern struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name, unsigned int mode, dev_t dev); -extern int gfs2_permission(struct inode *inode, int mask); +extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); -- cgit v1.2.2 From 24d9765fc18c7838ccdbb0d71fb706321d9b824c Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Tue, 18 Jan 2011 14:49:08 +0000 Subject: GFS2: Fix error path in gfs2_lookup_by_inum() In the (impossible, except if there is fs corruption) error path in gfs2_lookup_by_inum() if the call to gfs2_inode_refresh() fails, it was leaving the function by calling iput() rather than iget_failed(). This would cause future lookups of the same inode to block forever. This patch fixes the problem by moving the call to gfs2_inode_refresh() into gfs2_inode_lookup() where iget_failed() is part of the error path already. Also this cleans up some unreachable code and makes gfs2_set_iop() static. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 732a183efdb3..3e00a66e7cbd 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -96,7 +96,6 @@ err: return -EIO; } -extern void gfs2_set_iop(struct inode *inode); extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, u64 no_addr, u64 no_formal_ino); extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, -- cgit v1.2.2 From 44ad37d69b2cc421d5b5c7ad7fed16230685b092 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Thu, 17 Mar 2011 16:19:58 -0400 Subject: GFS2: filesystem hang caused by incorrect lock order This patch fixes a deadlock in GFS2 where two processes are trying to reclaim an unlinked dinode: One holds the inode glock and calls gfs2_lookup_by_inum trying to look up the inode, which it can't, due to I_FREEING. The other has set I_FREEING from vfs and is at the beginning of gfs2_delete_inode waiting for the glock, which is held by the first. The solution is to add a new non_block parameter to the gfs2_iget function that causes it to return -ENOENT if the inode is being freed. Signed-off-by: Bob Peterson Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 3e00a66e7cbd..099ca305e518 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -97,7 +97,8 @@ err: } extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, - u64 no_addr, u64 no_formal_ino); + u64 no_addr, u64 no_formal_ino, + int non_block); extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, u64 *no_formal_ino, unsigned int blktype); -- cgit v1.2.2 From f42ab0852946c1fb5103682c5897eb3da908e4b0 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Thu, 14 Apr 2011 16:50:31 +0100 Subject: GFS2: Optimise glock lru and end of life inodes The GLF_LRU flag introduced in the previous patch can be used to check if a glock is on the lru list when a new holder is queued and if so remove it, without having first to get the lru_lock. The main purpose of this patch however is to optimise the glocks left over when an inode at end of life is being evicted. Previously such glocks were left with the GLF_LFLUSH flag set, so that when reclaimed, each one required a log flush. This patch resets the GLF_LFLUSH flag when there is nothing left to flush thus preventing later log flushes as glocks are reused or demoted. In order to do this, we need to keep track of the number of revokes which are outstanding, and also to clear the GLF_LFLUSH bit after a log commit when only revokes have been processed. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 099ca305e518..842346eae836 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -106,7 +106,6 @@ extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); extern int gfs2_inode_refresh(struct gfs2_inode *ip); -extern int gfs2_dinode_dealloc(struct gfs2_inode *inode); extern int gfs2_change_nlink(struct gfs2_inode *ip, int diff); extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, int is_root); -- cgit v1.2.2 From 4667a0ec32867865fd4deccf834594b3ea831baf Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 18 Apr 2011 14:18:09 +0100 Subject: GFS2: Make writeback more responsive to system conditions This patch adds writeback_control to writing back the AIL list. This means that we can then take advantage of the information we get in ->write_inode() in order to set off some pre-emptive writeback. In addition, the AIL code is cleaned up a bit to make it a bit simpler to understand. There is still more which can usefully be done in this area, but this is a good start at least. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 842346eae836..8d1344a4e673 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -102,7 +102,7 @@ extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr, u64 *no_formal_ino, unsigned int blktype); -extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr); +extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int nonblock); extern int gfs2_inode_refresh(struct gfs2_inode *ip); -- cgit v1.2.2 From 3d6ecb7d16fd4248fce58387a982a0756ad3fcc2 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 9 May 2011 13:30:08 +0100 Subject: GFS2: When adding a new dir entry, inc link count if it is a subdir This adds an increment of the link count when we add a new directory entry, if that entry is itself a directory. This means that we no longer need separate code to perform this operation. Now that both adding and removing directory entries automatically update the parent directory's link count if required, that makes the code shorter and simpler than before. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 8d1344a4e673..f9b8289deec5 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -106,7 +106,6 @@ extern struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr, int nonbl extern int gfs2_inode_refresh(struct gfs2_inode *ip); -extern int gfs2_change_nlink(struct gfs2_inode *ip, int diff); extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, int is_root); extern struct inode *gfs2_createi(struct gfs2_holder *ghs, -- cgit v1.2.2 From 94fb763b1a76a2000ad21f3119b05c90040acaf0 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Mon, 9 May 2011 13:36:10 +0100 Subject: GFS2: Remove gfs2_dinode_print() function This function was intended for debugging purposes, but it is not very useful. If we want to know what is on disk then all we need is a block number and gfs2_edit can give us much better information about what is there. Otherwise, if we are interested in what is stored in the in-core inode, it doesn't help us out there either. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index f9b8289deec5..7ed60aa1b61f 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -115,7 +115,6 @@ extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); extern void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf); -extern void gfs2_dinode_print(const struct gfs2_inode *ip); extern const struct inode_operations gfs2_file_iops; extern const struct inode_operations gfs2_dir_iops; -- cgit v1.2.2 From 160b4026dc3e75c0693d0123eca805e88cd200b6 Mon Sep 17 00:00:00 2001 From: Steven Whitehouse Date: Fri, 13 May 2011 10:34:59 +0100 Subject: GFS2: Clean up symlink creation This moves the symlink specific parts of inode creation into the function where we initialise the rest of the dinode. As a result we have one less place where we need to look up the inode's buffer. Signed-off-by: Steven Whitehouse --- fs/gfs2/inode.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'fs/gfs2/inode.h') diff --git a/fs/gfs2/inode.h b/fs/gfs2/inode.h index 7ed60aa1b61f..31606076f701 100644 --- a/fs/gfs2/inode.h +++ b/fs/gfs2/inode.h @@ -108,9 +108,6 @@ extern int gfs2_inode_refresh(struct gfs2_inode *ip); extern struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, int is_root); -extern struct inode *gfs2_createi(struct gfs2_holder *ghs, - const struct qstr *name, - unsigned int mode, dev_t dev); extern int gfs2_permission(struct inode *inode, int mask, unsigned int flags); extern int gfs2_setattr_simple(struct gfs2_inode *ip, struct iattr *attr); extern struct inode *gfs2_lookup_simple(struct inode *dip, const char *name); -- cgit v1.2.2