]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/namespace.c
Merge branch 'limits' of https://github.com/deepa-hub/vfs into y2038
[linux.git] / fs / namespace.c
index 6464ea4acba9418f489fe8d5f867f55ef232b4e3..eae46531405f0dfd79590f60a2dd21cab5612a47 100644 (file)
@@ -1463,7 +1463,6 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
                        p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
 
                disconnect = disconnect_mount(p, how);
-
                if (mnt_has_parent(p)) {
                        mnt_add_count(p->mnt_parent, -1);
                        if (!disconnect) {
@@ -1471,10 +1470,11 @@ static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
                                list_add_tail(&p->mnt_child, &p->mnt_parent->mnt_mounts);
                        } else {
                                umount_mnt(p);
-                               hlist_add_head(&p->mnt_umount, &unmounted);
                        }
                }
                change_mnt_propagation(p, MS_PRIVATE);
+               if (disconnect)
+                       hlist_add_head(&p->mnt_umount, &unmounted);
        }
 }
 
@@ -2463,6 +2463,26 @@ static void set_mount_attributes(struct mount *mnt, unsigned int mnt_flags)
        unlock_mount_hash();
 }
 
+static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *mnt)
+{
+       struct super_block *sb = mnt->mnt_sb;
+
+       if (!__mnt_is_readonly(mnt) &&
+          (ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
+               char *buf = (char *)__get_free_page(GFP_KERNEL);
+               char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
+               struct tm tm;
+
+               time64_to_tm(sb->s_time_max, 0, &tm);
+
+               pr_warn("Mounted %s file system at %s supports timestamps until %04ld (0x%llx)\n",
+                       sb->s_type->name, mntpath,
+                       tm.tm_year+1900, (unsigned long long)sb->s_time_max);
+
+               free_page((unsigned long)buf);
+       }
+}
+
 /*
  * Handle reconfiguration of the mountpoint only without alteration of the
  * superblock it refers to.  This is triggered by specifying MS_REMOUNT|MS_BIND
@@ -2488,6 +2508,9 @@ static int do_reconfigure_mnt(struct path *path, unsigned int mnt_flags)
        if (ret == 0)
                set_mount_attributes(mnt, mnt_flags);
        up_write(&sb->s_umount);
+
+       mnt_warn_timestamp_expiry(path, &mnt->mnt);
+
        return ret;
 }
 
@@ -2528,6 +2551,9 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags,
                }
                up_write(&sb->s_umount);
        }
+
+       mnt_warn_timestamp_expiry(path, &mnt->mnt);
+
        put_fs_context(fc);
        return err;
 }
@@ -2736,8 +2762,13 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
                return PTR_ERR(mnt);
 
        error = do_add_mount(real_mount(mnt), mountpoint, mnt_flags);
-       if (error < 0)
+       if (error < 0) {
                mntput(mnt);
+               return error;
+       }
+
+       mnt_warn_timestamp_expiry(mountpoint, mnt);
+
        return error;
 }