fs: use backing_file container for internal files with "fake" f_path
[linux-2.6-block.git] / fs / open.c
index 322e017bf480860374fd3f841112dedcfb343f95..81186b277815453550ea4ba37881e53ee854b620 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -1149,23 +1149,44 @@ struct file *kernel_file_open(const struct path *path, int flags,
 }
 EXPORT_SYMBOL_GPL(kernel_file_open);
 
-struct file *open_with_fake_path(const struct path *path, int flags,
-                               struct inode *inode, const struct cred *cred)
+/**
+ * backing_file_open - open a backing file for kernel internal use
+ * @path:      path of the file to open
+ * @flags:     open flags
+ * @path:      path of the backing file
+ * @cred:      credentials for open
+ *
+ * Open a backing file for a stackable filesystem (e.g., overlayfs).
+ * @path may be on the stackable filesystem and backing inode on the
+ * underlying filesystem. In this case, we want to be able to return
+ * the @real_path of the backing inode. This is done by embedding the
+ * returned file into a container structure that also stores the path of
+ * the backing inode on the underlying filesystem, which can be
+ * retrieved using backing_file_real_path().
+ */
+struct file *backing_file_open(const struct path *path, int flags,
+                              const struct path *real_path,
+                              const struct cred *cred)
 {
-       struct file *f = alloc_empty_file_noaccount(flags, cred);
-       if (!IS_ERR(f)) {
-               int error;
+       struct file *f;
+       int error;
 
-               f->f_path = *path;
-               error = do_dentry_open(f, inode, NULL);
-               if (error) {
-                       fput(f);
-                       f = ERR_PTR(error);
-               }
+       f = alloc_empty_backing_file(flags, cred);
+       if (IS_ERR(f))
+               return f;
+
+       f->f_path = *path;
+       path_get(real_path);
+       *backing_file_real_path(f) = *real_path;
+       error = do_dentry_open(f, d_inode(real_path->dentry), NULL);
+       if (error) {
+               fput(f);
+               f = ERR_PTR(error);
        }
+
        return f;
 }
-EXPORT_SYMBOL(open_with_fake_path);
+EXPORT_SYMBOL_GPL(backing_file_open);
 
 #define WILL_CREATE(flags)     (flags & (O_CREAT | __O_TMPFILE))
 #define O_PATH_FLAGS           (O_DIRECTORY | O_NOFOLLOW | O_PATH | O_CLOEXEC)