This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / include / linux / vs_cowbl.h
diff --git a/include/linux/vs_cowbl.h b/include/linux/vs_cowbl.h
new file mode 100644 (file)
index 0000000..b4fff2d
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _VS_COWBL_H
+#define _VS_COWBL_H
+
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+
+extern struct dentry *cow_break_link(const char *pathname);
+
+static inline int cow_check_and_break(struct nameidata *nd)
+{
+       struct inode *inode = nd->dentry->d_inode;
+       int error = 0;
+       if (IS_RDONLY(inode) || MNT_IS_RDONLY(nd->mnt))
+               return -EROFS;
+       if (IS_COW(inode)) {
+               if (IS_COW_LINK(inode)) {
+                       struct dentry *new_dentry, *old_dentry = nd->dentry;
+                       char *path, *buf;
+
+                       buf = kmalloc(PATH_MAX, GFP_KERNEL);
+                       if (!buf) {
+                               return -ENOMEM;
+                       }
+                       path = d_path(nd->dentry, nd->mnt, buf, PATH_MAX);
+                       new_dentry = cow_break_link(path);
+                       kfree(buf);
+                       if (!IS_ERR(new_dentry)) {
+                               nd->dentry = new_dentry;
+                               dput(old_dentry);
+                       } else
+                               error = PTR_ERR(new_dentry);
+               } else {
+                       inode->i_flags &= ~(S_IUNLINK|S_IMMUTABLE);
+                       inode->i_ctime = CURRENT_TIME;
+                       mark_inode_dirty(inode);
+               }
+       }
+       return error;
+}
+
+#else
+#warning duplicate inclusion
+#endif