|
@@ -21,6 +21,8 @@
|
|
|
#include <linux/time.h>
|
|
|
#include <linux/fs.h>
|
|
|
#include <linux/jbd2.h>
|
|
|
+#include <linux/mount.h>
|
|
|
+#include <linux/path.h>
|
|
|
#include "ext4.h"
|
|
|
#include "ext4_jbd2.h"
|
|
|
#include "xattr.h"
|
|
@@ -145,6 +147,38 @@ static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int ext4_file_open(struct inode * inode, struct file * filp)
|
|
|
+{
|
|
|
+ struct super_block *sb = inode->i_sb;
|
|
|
+ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
|
|
|
+ struct vfsmount *mnt = filp->f_path.mnt;
|
|
|
+ struct path path;
|
|
|
+ char buf[64], *cp;
|
|
|
+
|
|
|
+ if (unlikely(!(sbi->s_mount_flags & EXT4_MF_MNTDIR_SAMPLED) &&
|
|
|
+ !(sb->s_flags & MS_RDONLY))) {
|
|
|
+ sbi->s_mount_flags |= EXT4_MF_MNTDIR_SAMPLED;
|
|
|
+ /*
|
|
|
+ * Sample where the filesystem has been mounted and
|
|
|
+ * store it in the superblock for sysadmin convenience
|
|
|
+ * when trying to sort through large numbers of block
|
|
|
+ * devices or filesystem images.
|
|
|
+ */
|
|
|
+ memset(buf, 0, sizeof(buf));
|
|
|
+ path.mnt = mnt->mnt_parent;
|
|
|
+ path.dentry = mnt->mnt_mountpoint;
|
|
|
+ path_get(&path);
|
|
|
+ cp = d_path(&path, buf, sizeof(buf));
|
|
|
+ path_put(&path);
|
|
|
+ if (!IS_ERR(cp)) {
|
|
|
+ memcpy(sbi->s_es->s_last_mounted, cp,
|
|
|
+ sizeof(sbi->s_es->s_last_mounted));
|
|
|
+ sb->s_dirt = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return generic_file_open(inode, filp);
|
|
|
+}
|
|
|
+
|
|
|
const struct file_operations ext4_file_operations = {
|
|
|
.llseek = generic_file_llseek,
|
|
|
.read = do_sync_read,
|
|
@@ -156,7 +190,7 @@ const struct file_operations ext4_file_operations = {
|
|
|
.compat_ioctl = ext4_compat_ioctl,
|
|
|
#endif
|
|
|
.mmap = ext4_file_mmap,
|
|
|
- .open = generic_file_open,
|
|
|
+ .open = ext4_file_open,
|
|
|
.release = ext4_release_file,
|
|
|
.fsync = ext4_sync_file,
|
|
|
.splice_read = generic_file_splice_read,
|