summaryrefslogtreecommitdiff
path: root/fs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/inode.c')
-rw-r--r--fs/inode.c90
1 files changed, 69 insertions, 21 deletions
diff --git a/fs/inode.c b/fs/inode.c
index d9a21d122926..bf21dc6d0dbd 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -97,7 +97,7 @@ static DEFINE_MUTEX(iprune_mutex);
*/
struct inodes_stat_t inodes_stat;
-static kmem_cache_t * inode_cachep __read_mostly;
+static struct kmem_cache * inode_cachep __read_mostly;
static struct inode *alloc_inode(struct super_block *sb)
{
@@ -109,7 +109,7 @@ static struct inode *alloc_inode(struct super_block *sb)
if (sb->s_op->alloc_inode)
inode = sb->s_op->alloc_inode(sb);
else
- inode = (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL);
+ inode = (struct inode *) kmem_cache_alloc(inode_cachep, GFP_KERNEL);
if (inode) {
struct address_space * const mapping = &inode->i_data;
@@ -209,7 +209,7 @@ void inode_init_once(struct inode *inode)
EXPORT_SYMBOL(inode_init_once);
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
{
struct inode * inode = (struct inode *) foo;
@@ -1144,7 +1144,6 @@ sector_t bmap(struct inode * inode, sector_t block)
res = inode->i_mapping->a_ops->bmap(inode->i_mapping, block);
return res;
}
-
EXPORT_SYMBOL(bmap);
/**
@@ -1163,27 +1162,43 @@ void touch_atime(struct vfsmount *mnt, struct dentry *dentry)
if (IS_RDONLY(inode))
return;
-
- if ((inode->i_flags & S_NOATIME) ||
- (inode->i_sb->s_flags & MS_NOATIME) ||
- ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode)))
+ if (inode->i_flags & S_NOATIME)
+ return;
+ if (inode->i_sb->s_flags & MS_NOATIME)
+ return;
+ if ((inode->i_sb->s_flags & MS_NODIRATIME) && S_ISDIR(inode->i_mode))
return;
/*
* We may have a NULL vfsmount when coming from NFSD
*/
- if (mnt &&
- ((mnt->mnt_flags & MNT_NOATIME) ||
- ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))))
- return;
+ if (mnt) {
+ if (mnt->mnt_flags & MNT_NOATIME)
+ return;
+ if ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))
+ return;
- now = current_fs_time(inode->i_sb);
- if (!timespec_equal(&inode->i_atime, &now)) {
- inode->i_atime = now;
- mark_inode_dirty_sync(inode);
+ if (mnt->mnt_flags & MNT_RELATIME) {
+ /*
+ * With relative atime, only update atime if the
+ * previous atime is earlier than either the ctime or
+ * mtime.
+ */
+ if (timespec_compare(&inode->i_mtime,
+ &inode->i_atime) < 0 &&
+ timespec_compare(&inode->i_ctime,
+ &inode->i_atime) < 0)
+ return;
+ }
}
-}
+ now = current_fs_time(inode->i_sb);
+ if (timespec_equal(&inode->i_atime, &now))
+ return;
+
+ inode->i_atime = now;
+ mark_inode_dirty_sync(inode);
+}
EXPORT_SYMBOL(touch_atime);
/**
@@ -1200,7 +1215,7 @@ EXPORT_SYMBOL(touch_atime);
void file_update_time(struct file *file)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
struct timespec now;
int sync_it = 0;
@@ -1242,9 +1257,6 @@ EXPORT_SYMBOL(inode_needs_sync);
*/
#ifdef CONFIG_QUOTA
-/* Function back in dquot.c */
-int remove_inode_dquot_ref(struct inode *, int, struct list_head *);
-
void remove_dquot_ref(struct super_block *sb, int type,
struct list_head *tofree_head)
{
@@ -1306,6 +1318,42 @@ void wake_up_inode(struct inode *inode)
wake_up_bit(&inode->i_state, __I_LOCK);
}
+/*
+ * We rarely want to lock two inodes that do not have a parent/child
+ * relationship (such as directory, child inode) simultaneously. The
+ * vast majority of file systems should be able to get along fine
+ * without this. Do not use these functions except as a last resort.
+ */
+void inode_double_lock(struct inode *inode1, struct inode *inode2)
+{
+ if (inode1 == NULL || inode2 == NULL || inode1 == inode2) {
+ if (inode1)
+ mutex_lock(&inode1->i_mutex);
+ else if (inode2)
+ mutex_lock(&inode2->i_mutex);
+ return;
+ }
+
+ if (inode1 < inode2) {
+ mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
+ mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
+ } else {
+ mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT);
+ mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD);
+ }
+}
+EXPORT_SYMBOL(inode_double_lock);
+
+void inode_double_unlock(struct inode *inode1, struct inode *inode2)
+{
+ if (inode1)
+ mutex_unlock(&inode1->i_mutex);
+
+ if (inode2 && inode2 != inode1)
+ mutex_unlock(&inode2->i_mutex);
+}
+EXPORT_SYMBOL(inode_double_unlock);
+
static __initdata unsigned long ihash_entries;
static int __init set_ihash_entries(char *str)
{