SUNRPC: xprt_connect() don't abort the task if the transport isn't bound
[safe/jmp/linux-2.6] / fs / ocfs2 / namei.c
index e8ff0ba..084aba8 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/highmem.h>
+#include <linux/quotaops.h>
 
 #define MLOG_MASK_PREFIX ML_NAMEI
 #include <cluster/masklog.h>
@@ -61,6 +62,7 @@
 #include "sysfile.h"
 #include "uptodate.h"
 #include "xattr.h"
+#include "acl.h"
 
 #include "buffer_head_io.h"
 
@@ -211,6 +213,7 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, int mode)
        } else
                inode->i_gid = current_fsgid();
        inode->i_mode = mode;
+       vfs_dq_init(inode);
        return inode;
 }
 
@@ -229,6 +232,13 @@ static int ocfs2_mknod(struct inode *dir,
        struct inode *inode = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, %d, %lu, '%.*s')\n", dir, dentry, mode,
                   (unsigned long)dev, dentry->d_name.len,
@@ -285,17 +295,39 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       /* Reserve a cluster if creating an extent based directory. */
-       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
-               if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
                        goto leave;
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_MKNOD_CREDITS);
+       /* calculate meta data/clusters for setting security and acl xattr */
+       status = ocfs2_calc_xattr_init(dir, parent_fe_bh, mode,
+                                       &si, &want_clusters,
+                                       &xattr_credits, &xattr_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       /* Reserve a cluster if creating an extent based directory. */
+       if (S_ISDIR(mode) && !ocfs2_supports_inline_data(osb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto leave;
+       }
+
+       handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb) +
+                                  xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -303,6 +335,15 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto leave;
+       }
+       did_quota_inode = 1;
+
        /* do the real work now. */
        status = ocfs2_mknod_locked(osb, dir, inode, dentry, dev,
                                    &new_fe_bh, parent_fe_bh, handle,
@@ -320,8 +361,8 @@ static int ocfs2_mknod(struct inode *dir,
                        goto leave;
                }
 
-               status = ocfs2_journal_access(handle, dir, parent_fe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, dir, parent_fe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto leave;
@@ -335,6 +376,22 @@ static int ocfs2_mknod(struct inode *dir,
                inc_nlink(dir);
        }
 
+       status = ocfs2_init_acl(handle, inode, dir, new_fe_bh, parent_fe_bh,
+                               xattr_ac, data_ac);
+       if (status < 0) {
+               mlog_errno(status);
+               goto leave;
+       }
+
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto leave;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 OCFS2_I(inode)->ip_blkno, parent_fe_bh,
                                 de_bh);
@@ -355,6 +412,8 @@ static int ocfs2_mknod(struct inode *dir,
        d_instantiate(dentry, inode);
        status = 0;
 leave:
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -366,6 +425,8 @@ leave:
        brelse(new_fe_bh);
        brelse(de_bh);
        brelse(parent_fe_bh);
+       kfree(si.name);
+       kfree(si.value);
 
        if ((status < 0) && inode) {
                clear_nlink(inode);
@@ -378,6 +439,9 @@ leave:
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
 
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
+
        mlog_exit(status);
 
        return status;
@@ -429,8 +493,8 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
        }
        ocfs2_set_new_buffer_uptodate(inode, *new_fe_bh);
 
-       status = ocfs2_journal_access(handle, inode, *new_fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_CREATE);
+       status = ocfs2_journal_access_di(handle, inode, *new_fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_CREATE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -482,15 +546,7 @@ static int ocfs2_mknod_locked(struct ocfs2_super *osb,
                goto leave;
        }
 
-       if (ocfs2_populate_inode(inode, fe, 1) < 0) {
-               mlog(ML_ERROR, "populate inode failed! bh->b_blocknr=%llu, "
-                    "i_blkno=%llu, i_ino=%lu\n",
-                    (unsigned long long)(*new_fe_bh)->b_blocknr,
-                    (unsigned long long)le64_to_cpu(fe->i_blkno),
-                    inode->i_ino);
-               BUG();
-       }
-
+       ocfs2_populate_inode(inode, fe, 1);
        ocfs2_inode_set_new(osb, inode);
        if (!ocfs2_mount_local(osb)) {
                status = ocfs2_create_new_inode_locks(inode);
@@ -600,7 +656,7 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_LINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_link_credits(osb->sb));
        if (IS_ERR(handle)) {
                err = PTR_ERR(handle);
                handle = NULL;
@@ -608,8 +664,8 @@ static int ocfs2_link(struct dentry *old_dentry,
                goto out_unlock_inode;
        }
 
-       err = ocfs2_journal_access(handle, inode, fe_bh,
-                                  OCFS2_JOURNAL_ACCESS_WRITE);
+       err = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                     OCFS2_JOURNAL_ACCESS_WRITE);
        if (err < 0) {
                mlog_errno(err);
                goto out_commit;
@@ -787,7 +843,7 @@ static int ocfs2_unlink(struct inode *dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_UNLINK_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_unlink_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -795,8 +851,8 @@ static int ocfs2_unlink(struct inode *dir,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, inode, fe_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, inode, fe_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1193,7 +1249,7 @@ static int ocfs2_rename(struct inode *old_dir,
                }
        }
 
-       handle = ocfs2_start_trans(osb, OCFS2_RENAME_CREDITS);
+       handle = ocfs2_start_trans(osb, ocfs2_rename_credits(osb->sb));
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1209,8 +1265,8 @@ static int ocfs2_rename(struct inode *old_dir,
                                goto bail;
                        }
                }
-               status = ocfs2_journal_access(handle, new_inode, newfe_bh,
-                                             OCFS2_JOURNAL_ACCESS_WRITE);
+               status = ocfs2_journal_access_di(handle, new_inode, newfe_bh,
+                                                OCFS2_JOURNAL_ACCESS_WRITE);
                if (status < 0) {
                        mlog_errno(status);
                        goto bail;
@@ -1256,8 +1312,8 @@ static int ocfs2_rename(struct inode *old_dir,
        old_inode->i_ctime = CURRENT_TIME;
        mark_inode_dirty(old_inode);
 
-       status = ocfs2_journal_access(handle, old_inode, old_inode_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, old_inode, old_inode_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status >= 0) {
                old_di = (struct ocfs2_dinode *) old_inode_bh->b_data;
 
@@ -1333,9 +1389,9 @@ static int ocfs2_rename(struct inode *old_dir,
                             (int)old_dir_nlink, old_dir->i_nlink);
                } else {
                        struct ocfs2_dinode *fe;
-                       status = ocfs2_journal_access(handle, old_dir,
-                                                     old_dir_bh,
-                                                     OCFS2_JOURNAL_ACCESS_WRITE);
+                       status = ocfs2_journal_access_di(handle, old_dir,
+                                                        old_dir_bh,
+                                                        OCFS2_JOURNAL_ACCESS_WRITE);
                        fe = (struct ocfs2_dinode *) old_dir_bh->b_data;
                        fe->i_links_count = cpu_to_le16(old_dir->i_nlink);
                        status = ocfs2_journal_dirty(handle, old_dir_bh);
@@ -1508,6 +1564,13 @@ static int ocfs2_symlink(struct inode *dir,
        handle_t *handle = NULL;
        struct ocfs2_alloc_context *inode_ac = NULL;
        struct ocfs2_alloc_context *data_ac = NULL;
+       struct ocfs2_alloc_context *xattr_ac = NULL;
+       int want_clusters = 0;
+       int xattr_credits = 0;
+       struct ocfs2_security_xattr_info si = {
+               .enable = 1,
+       };
+       int did_quota = 0, did_quota_inode = 0;
 
        mlog_entry("(0x%p, 0x%p, symname='%s' actual='%.*s')\n", dir,
                   dentry, symname, dentry->d_name.len, dentry->d_name.name);
@@ -1561,17 +1624,39 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
-       /* don't reserve bitmap space for fast symlinks. */
-       if (l > ocfs2_fast_symlink_chars(sb)) {
-               status = ocfs2_reserve_clusters(osb, 1, &data_ac);
+       /* get security xattr */
+       status = ocfs2_init_security_get(inode, dir, &si);
+       if (status) {
+               if (status == -EOPNOTSUPP)
+                       si.enable = 0;
+               else {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
+       /* calculate meta data/clusters for setting security xattr */
+       if (si.enable) {
+               status = ocfs2_calc_security_init(dir, &si, &want_clusters,
+                                                 &xattr_credits, &xattr_ac);
                if (status < 0) {
-                       if (status != -ENOSPC)
-                               mlog_errno(status);
+                       mlog_errno(status);
                        goto bail;
                }
        }
 
-       handle = ocfs2_start_trans(osb, credits);
+       /* don't reserve bitmap space for fast symlinks. */
+       if (l > ocfs2_fast_symlink_chars(sb))
+               want_clusters += 1;
+
+       status = ocfs2_reserve_clusters(osb, want_clusters, &data_ac);
+       if (status < 0) {
+               if (status != -ENOSPC)
+                       mlog_errno(status);
+               goto bail;
+       }
+
+       handle = ocfs2_start_trans(osb, credits + xattr_credits);
        if (IS_ERR(handle)) {
                status = PTR_ERR(handle);
                handle = NULL;
@@ -1579,6 +1664,15 @@ static int ocfs2_symlink(struct inode *dir,
                goto bail;
        }
 
+       /* We don't use standard VFS wrapper because we don't want vfs_dq_init
+        * to be called. */
+       if (sb_any_quota_active(osb->sb) &&
+           osb->sb->dq_op->alloc_inode(inode, 1) == NO_QUOTA) {
+               status = -EDQUOT;
+               goto bail;
+       }
+       did_quota_inode = 1;
+
        status = ocfs2_mknod_locked(osb, dir, inode, dentry,
                                    0, &new_fe_bh, parent_fe_bh, handle,
                                    inode_ac);
@@ -1594,6 +1688,12 @@ static int ocfs2_symlink(struct inode *dir,
                u32 offset = 0;
 
                inode->i_op = &ocfs2_symlink_inode_operations;
+               if (vfs_dq_alloc_space_nodirty(inode,
+                   ocfs2_clusters_to_bytes(osb->sb, 1))) {
+                       status = -EDQUOT;
+                       goto bail;
+               }
+               did_quota = 1;
                status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
                                              new_fe_bh,
                                              handle, data_ac, NULL,
@@ -1632,6 +1732,15 @@ static int ocfs2_symlink(struct inode *dir,
                }
        }
 
+       if (si.enable) {
+               status = ocfs2_init_security_set(handle, inode, new_fe_bh, &si,
+                                                xattr_ac, data_ac);
+               if (status < 0) {
+                       mlog_errno(status);
+                       goto bail;
+               }
+       }
+
        status = ocfs2_add_entry(handle, dentry, inode,
                                 le64_to_cpu(fe->i_blkno), parent_fe_bh,
                                 de_bh);
@@ -1650,6 +1759,11 @@ static int ocfs2_symlink(struct inode *dir,
        dentry->d_op = &ocfs2_dentry_ops;
        d_instantiate(dentry, inode);
 bail:
+       if (status < 0 && did_quota)
+               vfs_dq_free_space_nodirty(inode,
+                                       ocfs2_clusters_to_bytes(osb->sb, 1));
+       if (status < 0 && did_quota_inode)
+               vfs_dq_free_inode(inode);
        if (handle)
                ocfs2_commit_trans(osb, handle);
 
@@ -1658,10 +1772,14 @@ bail:
        brelse(new_fe_bh);
        brelse(parent_fe_bh);
        brelse(de_bh);
+       kfree(si.name);
+       kfree(si.value);
        if (inode_ac)
                ocfs2_free_alloc_context(inode_ac);
        if (data_ac)
                ocfs2_free_alloc_context(data_ac);
+       if (xattr_ac)
+               ocfs2_free_alloc_context(xattr_ac);
        if ((status < 0) && inode) {
                clear_nlink(inode);
                iput(inode);
@@ -1774,16 +1892,14 @@ static int ocfs2_orphan_add(struct ocfs2_super *osb,
 
        mlog_entry("(inode->i_ino = %lu)\n", inode->i_ino);
 
-       status = ocfs2_read_block(orphan_dir_inode,
-                                 OCFS2_I(orphan_dir_inode)->ip_blkno,
-                                 &orphan_dir_bh);
+       status = ocfs2_read_inode_block(orphan_dir_inode, &orphan_dir_bh);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle, orphan_dir_inode, orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle, orphan_dir_inode, orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;
@@ -1870,8 +1986,8 @@ int ocfs2_orphan_del(struct ocfs2_super *osb,
                goto leave;
        }
 
-       status = ocfs2_journal_access(handle,orphan_dir_inode,  orphan_dir_bh,
-                                     OCFS2_JOURNAL_ACCESS_WRITE);
+       status = ocfs2_journal_access_di(handle,orphan_dir_inode,  orphan_dir_bh,
+                                        OCFS2_JOURNAL_ACCESS_WRITE);
        if (status < 0) {
                mlog_errno(status);
                goto leave;