nfsd: Remove callback_cred
[linux-2.6-microblaze.git] / fs / inode.c
index 13ceb98..2c300e9 100644 (file)
@@ -178,6 +178,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        mapping->a_ops = &empty_aops;
        mapping->host = inode;
        mapping->flags = 0;
+       mapping->wb_err = 0;
        atomic_set(&mapping->i_mmap_writable, 0);
        mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);
        mapping->private_data = NULL;
@@ -1002,6 +1003,70 @@ void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2)
 }
 EXPORT_SYMBOL(unlock_two_nondirectories);
 
+/**
+ * inode_insert5 - obtain an inode from a mounted file system
+ * @inode:     pre-allocated inode to use for insert to cache
+ * @hashval:   hash value (usually inode number) to get
+ * @test:      callback used for comparisons between inodes
+ * @set:       callback used to initialize a new struct inode
+ * @data:      opaque data pointer to pass to @test and @set
+ *
+ * Search for the inode specified by @hashval and @data in the inode cache,
+ * and if present it is return it with an increased reference count. This is
+ * a variant of iget5_locked() for callers that don't want to fail on memory
+ * allocation of inode.
+ *
+ * If the inode is not in cache, insert the pre-allocated inode to cache and
+ * return it locked, hashed, and with the I_NEW flag set. The file system gets
+ * to fill it in before unlocking it via unlock_new_inode().
+ *
+ * Note both @test and @set are called with the inode_hash_lock held, so can't
+ * sleep.
+ */
+struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
+                           int (*test)(struct inode *, void *),
+                           int (*set)(struct inode *, void *), void *data)
+{
+       struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval);
+       struct inode *old;
+
+again:
+       spin_lock(&inode_hash_lock);
+       old = find_inode(inode->i_sb, head, test, data);
+       if (unlikely(old)) {
+               /*
+                * Uhhuh, somebody else created the same inode under us.
+                * Use the old inode instead of the preallocated one.
+                */
+               spin_unlock(&inode_hash_lock);
+               wait_on_inode(old);
+               if (unlikely(inode_unhashed(old))) {
+                       iput(old);
+                       goto again;
+               }
+               return old;
+       }
+
+       if (set && unlikely(set(inode, data))) {
+               inode = NULL;
+               goto unlock;
+       }
+
+       /*
+        * Return the locked inode with I_NEW set, the
+        * caller is responsible for filling in the contents
+        */
+       spin_lock(&inode->i_lock);
+       inode->i_state |= I_NEW;
+       hlist_add_head(&inode->i_hash, head);
+       spin_unlock(&inode->i_lock);
+unlock:
+       spin_unlock(&inode_hash_lock);
+
+       return inode;
+}
+EXPORT_SYMBOL(inode_insert5);
+
 /**
  * iget5_locked - obtain an inode from a mounted file system
  * @sb:                super block of file system
@@ -1026,66 +1091,18 @@ struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
                int (*test)(struct inode *, void *),
                int (*set)(struct inode *, void *), void *data)
 {
-       struct hlist_head *head = inode_hashtable + hash(sb, hashval);
-       struct inode *inode;
-again:
-       spin_lock(&inode_hash_lock);
-       inode = find_inode(sb, head, test, data);
-       spin_unlock(&inode_hash_lock);
-
-       if (inode) {
-               wait_on_inode(inode);
-               if (unlikely(inode_unhashed(inode))) {
-                       iput(inode);
-                       goto again;
-               }
-               return inode;
-       }
-
-       inode = alloc_inode(sb);
-       if (inode) {
-               struct inode *old;
-
-               spin_lock(&inode_hash_lock);
-               /* We released the lock, so.. */
-               old = find_inode(sb, head, test, data);
-               if (!old) {
-                       if (set(inode, data))
-                               goto set_failed;
-
-                       spin_lock(&inode->i_lock);
-                       inode->i_state = I_NEW;
-                       hlist_add_head(&inode->i_hash, head);
-                       spin_unlock(&inode->i_lock);
-                       inode_sb_list_add(inode);
-                       spin_unlock(&inode_hash_lock);
+       struct inode *inode = ilookup5(sb, hashval, test, data);
 
-                       /* Return the locked inode with I_NEW set, the
-                        * caller is responsible for filling in the contents
-                        */
-                       return inode;
-               }
+       if (!inode) {
+               struct inode *new = new_inode(sb);
 
-               /*
-                * Uhhuh, somebody else created the same inode under
-                * us. Use the old inode instead of the one we just
-                * allocated.
-                */
-               spin_unlock(&inode_hash_lock);
-               destroy_inode(inode);
-               inode = old;
-               wait_on_inode(inode);
-               if (unlikely(inode_unhashed(inode))) {
-                       iput(inode);
-                       goto again;
+               if (new) {
+                       inode = inode_insert5(new, hashval, test, set, data);
+                       if (unlikely(inode != new))
+                               iput(new);
                }
        }
        return inode;
-
-set_failed:
-       spin_unlock(&inode_hash_lock);
-       destroy_inode(inode);
-       return NULL;
 }
 EXPORT_SYMBOL(iget5_locked);
 
@@ -1426,43 +1443,13 @@ EXPORT_SYMBOL(insert_inode_locked);
 int insert_inode_locked4(struct inode *inode, unsigned long hashval,
                int (*test)(struct inode *, void *), void *data)
 {
-       struct super_block *sb = inode->i_sb;
-       struct hlist_head *head = inode_hashtable + hash(sb, hashval);
-
-       while (1) {
-               struct inode *old = NULL;
+       struct inode *old = inode_insert5(inode, hashval, test, NULL, data);
 
-               spin_lock(&inode_hash_lock);
-               hlist_for_each_entry(old, head, i_hash) {
-                       if (old->i_sb != sb)
-                               continue;
-                       if (!test(old, data))
-                               continue;
-                       spin_lock(&old->i_lock);
-                       if (old->i_state & (I_FREEING|I_WILL_FREE)) {
-                               spin_unlock(&old->i_lock);
-                               continue;
-                       }
-                       break;
-               }
-               if (likely(!old)) {
-                       spin_lock(&inode->i_lock);
-                       inode->i_state |= I_NEW;
-                       hlist_add_head(&inode->i_hash, head);
-                       spin_unlock(&inode->i_lock);
-                       spin_unlock(&inode_hash_lock);
-                       return 0;
-               }
-               __iget(old);
-               spin_unlock(&old->i_lock);
-               spin_unlock(&inode_hash_lock);
-               wait_on_inode(old);
-               if (unlikely(!inode_unhashed(old))) {
-                       iput(old);
-                       return -EBUSY;
-               }
+       if (old != inode) {
                iput(old);
+               return -EBUSY;
        }
+       return 0;
 }
 EXPORT_SYMBOL(insert_inode_locked4);
 
@@ -1590,8 +1577,8 @@ static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
        if (upperdentry) {
                struct inode *realinode = d_inode(upperdentry);
 
-               if ((!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
-                    !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
+               if ((!timespec64_equal(&inode->i_mtime, &realinode->i_mtime) ||
+                    !timespec64_equal(&inode->i_ctime, &realinode->i_ctime))) {
                        inode->i_mtime = realinode->i_mtime;
                        inode->i_ctime = realinode->i_ctime;
                }
@@ -1614,12 +1601,12 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
        /*
         * Is mtime younger than atime? If yes, update atime:
         */
-       if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0)
+       if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
                return 1;
        /*
         * Is ctime younger than atime? If yes, update atime:
         */
-       if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0)
+       if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
                return 1;
 
        /*
@@ -1634,7 +1621,7 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
        return 0;
 }
 
-int generic_update_time(struct inode *inode, struct timespec *time, int flags)
+int generic_update_time(struct inode *inode, struct timespec64 *time, int flags)
 {
        int iflags = I_DIRTY_TIME;
        bool dirty = false;
@@ -1662,9 +1649,9 @@ EXPORT_SYMBOL(generic_update_time);
  * This does the actual work of updating an inodes time or version.  Must have
  * had called mnt_want_write() before calling this.
  */
-static int update_time(struct inode *inode, struct timespec *time, int flags)
+static int update_time(struct inode *inode, struct timespec64 *time, int flags)
 {
-       int (*update_time)(struct inode *, struct timespec *, int);
+       int (*update_time)(struct inode *, struct timespec64 *, int);
 
        update_time = inode->i_op->update_time ? inode->i_op->update_time :
                generic_update_time;
@@ -1685,7 +1672,7 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
                          bool rcu)
 {
        struct vfsmount *mnt = path->mnt;
-       struct timespec now;
+       struct timespec64 now;
 
        if (inode->i_flags & S_NOATIME)
                return false;
@@ -1708,10 +1695,10 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
 
        now = current_time(inode);
 
-       if (!relatime_need_update(path, inode, now, rcu))
+       if (!relatime_need_update(path, inode, timespec64_to_timespec(now), rcu))
                return false;
 
-       if (timespec_equal(&inode->i_atime, &now))
+       if (timespec64_equal(&inode->i_atime, &now))
                return false;
 
        return true;
@@ -1721,7 +1708,7 @@ void touch_atime(const struct path *path)
 {
        struct vfsmount *mnt = path->mnt;
        struct inode *inode = d_inode(path->dentry);
-       struct timespec now;
+       struct timespec64 now;
 
        if (!__atime_needs_update(path, inode, false))
                return;
@@ -1855,7 +1842,7 @@ EXPORT_SYMBOL(file_remove_privs);
 int file_update_time(struct file *file)
 {
        struct inode *inode = file_inode(file);
-       struct timespec now;
+       struct timespec64 now;
        int sync_it = 0;
        int ret;
 
@@ -1864,10 +1851,10 @@ int file_update_time(struct file *file)
                return 0;
 
        now = current_time(inode);
-       if (!timespec_equal(&inode->i_mtime, &now))
+       if (!timespec64_equal(&inode->i_mtime, &now))
                sync_it = S_MTIME;
 
-       if (!timespec_equal(&inode->i_ctime, &now))
+       if (!timespec64_equal(&inode->i_ctime, &now))
                sync_it |= S_CTIME;
 
        if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
@@ -2110,6 +2097,30 @@ void inode_nohighmem(struct inode *inode)
 }
 EXPORT_SYMBOL(inode_nohighmem);
 
+/**
+ * timespec64_trunc - Truncate timespec64 to a granularity
+ * @t: Timespec64
+ * @gran: Granularity in ns.
+ *
+ * Truncate a timespec64 to a granularity. Always rounds down. gran must
+ * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns).
+ */
+struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran)
+{
+       /* Avoid division in the common cases 1 ns and 1 s. */
+       if (gran == 1) {
+               /* nothing */
+       } else if (gran == NSEC_PER_SEC) {
+               t.tv_nsec = 0;
+       } else if (gran > 1 && gran < NSEC_PER_SEC) {
+               t.tv_nsec -= t.tv_nsec % gran;
+       } else {
+               WARN(1, "illegal file time granularity: %u", gran);
+       }
+       return t;
+}
+EXPORT_SYMBOL(timespec64_trunc);
+
 /**
  * current_time - Return FS time
  * @inode: inode.
@@ -2120,15 +2131,15 @@ EXPORT_SYMBOL(inode_nohighmem);
  * Note that inode and inode->sb cannot be NULL.
  * Otherwise, the function warns and returns time without truncation.
  */
-struct timespec current_time(struct inode *inode)
+struct timespec64 current_time(struct inode *inode)
 {
-       struct timespec now = current_kernel_time();
+       struct timespec64 now = current_kernel_time64();
 
        if (unlikely(!inode->i_sb)) {
                WARN(1, "current_time() called with uninitialized super_block in the inode");
                return now;
        }
 
-       return timespec_trunc(now, inode->i_sb->s_time_gran);
+       return timespec64_trunc(now, inode->i_sb->s_time_gran);
 }
 EXPORT_SYMBOL(current_time);