Whamcloud - gitweb
LU-7991 quota: project quota against ZFS backend
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_internal.h
index d44e389..c0bf3e8 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * version 2 along with this program; If not, see
- * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * GPL HEADER END
  */
@@ -27,7 +23,7 @@
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2011, 2015, Intel Corporation.
+ * Copyright (c) 2011, 2016, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
@@ -94,6 +90,13 @@ extern struct kmem_cache *dynlock_cachep;
 #define OSD_STATFS_RESERVED            (1ULL << 23) /* 8MB */
 #define OSD_STATFS_RESERVED_SHIFT      (7) /* reserve 0.78% of all space */
 
+/* check if ldiskfs support project quota */
+#ifndef LDISKFS_IOC_FSSETXATTR
+#undef HAVE_PROJECT_QUOTA
+#endif
+
+#define OBD_BRW_MAPPED OBD_BRW_LOCAL1
+
 struct osd_directory {
         struct iam_container od_container;
         struct iam_descr     od_descr;
@@ -113,19 +116,19 @@ struct osd_oi {
 extern const int osd_dto_credits_noquota[];
 
 struct osd_object {
-        struct dt_object        oo_dt;
-        /**
-         * Inode for file system object represented by this osd_object. This
-         * inode is pinned for the whole duration of lu_object life.
-         *
-         * Not modified concurrently (either setup early during object
-         * creation, or assigned by osd_object_create() under write lock).
-         */
-        struct inode           *oo_inode;
-        /**
-         * to protect index ops.
-         */
-        struct htree_lock_head *oo_hl_head;
+       struct dt_object        oo_dt;
+       /**
+        * Inode for file system object represented by this osd_object. This
+        * inode is pinned for the whole duration of lu_object life.
+        *
+        * Not modified concurrently (either setup early during object
+        * creation, or assigned by osd_create() under write lock).
+        */
+       struct inode           *oo_inode;
+       /**
+        * to protect index ops.
+        */
+       struct htree_lock_head *oo_hl_head;
        struct rw_semaphore     oo_ext_idx_sem;
        struct rw_semaphore     oo_sem;
        struct osd_directory    *oo_dir;
@@ -178,7 +181,7 @@ struct osd_mdobj {
 struct osd_mdobj_map {
        struct dentry   *omm_remote_parent;
 };
-int osd_ldiskfs_add_entry(struct osd_thread_info *info,
+int osd_ldiskfs_add_entry(struct osd_thread_info *info, struct osd_device *osd,
                          handle_t *handle, struct dentry *child,
                          struct inode *inode, struct htree_lock *hlock);
 
@@ -215,6 +218,7 @@ struct osd_otable_cache {
 struct osd_otable_it {
        struct osd_device       *ooi_dev;
        struct osd_otable_cache  ooi_cache;
+       struct osd_iit_param     ooi_iit_param;
 
        /* The following bits can be updated/checked w/o lock protection.
         * If more bits will be introduced in the future and need lock to
@@ -320,20 +324,19 @@ enum osd_full_scrub_ratio {
 
 #define FULL_SCRUB_THRESHOLD_RATE_DEFAULT      60
 
-/* There are at most 10 uid/gids are affected in a transaction, and
+/* There are at most 15 uid/gid/projids are affected in a transaction, and
  * that's rename case:
- * - 2 for source parent uid & gid;
- * - 2 for source child uid & gid ('..' entry update when child is directory);
- * - 2 for target parent uid & gid;
- * - 2 for target child uid & gid (if the target child exists);
- * - 2 for root uid & gid (last_rcvd, llog, etc);
+ * - 3 for source parent uid & gid & projid;
+ * - 3 for source child uid & gid & projid ('..' entry update when
+ * child is directory);
+ * - 3 for target parent uid & gid & projid;
+ * - 3 for target child uid & gid & projid(if the target child exists);
+ * - 3 for root uid & gid(last_rcvd, llog, etc);
  *
- * The 0 to (OSD_MAX_UGID_CNT - 1) bits of ot_id_type is for indicating
- * the id type of each id in the ot_id_array.
  */
-#define OSD_MAX_UGID_CNT        10
+#define OSD_MAX_UGID_CNT        15
 
-enum {
+enum osd_op_type {
        OSD_OT_ATTR_SET         = 0,
        OSD_OT_PUNCH            = 1,
        OSD_OT_XATTR_SET        = 2,
@@ -356,18 +359,18 @@ struct osd_thandle {
        struct list_head       ot_stop_dcb_list;
        /* Link to the device, for debugging. */
        struct lu_ref_link      ot_dev_link;
-        unsigned short          ot_credits;
-        unsigned short          ot_id_cnt;
-        unsigned short          ot_id_type;
+       unsigned int            ot_credits;
+       unsigned short          ot_id_cnt;
+       __u8                    ot_id_types[OSD_MAX_UGID_CNT];
        unsigned int            ot_remove_agents:1;
-        uid_t                   ot_id_array[OSD_MAX_UGID_CNT];
+       uid_t                   ot_id_array[OSD_MAX_UGID_CNT];
        struct lquota_trans    *ot_quota_trans;
 #if OSD_THANDLE_STATS
         /** time when this handle was allocated */
-        cfs_time_t oth_alloced;
+       ktime_t oth_alloced;
 
         /** time when this thanle was started */
-        cfs_time_t oth_started;
+       ktime_t oth_started;
 #endif
 };
 
@@ -438,7 +441,7 @@ struct osd_it_ea_dirent {
  * there  would be one ext3 readdir for every mdd readdir page.
  */
 
-#define OSD_IT_EA_BUFSIZE       (PAGE_CACHE_SIZE + PAGE_CACHE_SIZE/4)
+#define OSD_IT_EA_BUFSIZE       (PAGE_SIZE + PAGE_SIZE/4)
 
 /**
  * This is iterator's in-memory data structure in interoperability
@@ -490,7 +493,7 @@ struct osd_it_quota {
        struct list_head         oiq_list;
 };
 
-#define MAX_BLOCKS_PER_PAGE (PAGE_CACHE_SIZE / 512)
+#define MAX_BLOCKS_PER_PAGE (PAGE_SIZE / 512)
 
 struct osd_iobuf {
        wait_queue_head_t  dr_wait;
@@ -547,10 +550,6 @@ struct osd_thread_info {
          */
         struct timespec        oti_time;
 
-        /** osd_device reference, initialized in osd_trans_start() and
-            used in osd_trans_stop() */
-        struct osd_device     *oti_dev;
-
         /**
          * following ipd and it structures are used for osd_index_iam_lookup()
          * these are defined separately as we might do index operation
@@ -591,9 +590,7 @@ struct osd_thread_info {
        struct lu_buf          oti_big_buf;
         /** used in osd_ea_fid_set() to set fid into common ea */
        union {
-               struct lustre_mdt_attrs oti_mdt_attrs;
-               /* old LMA for compatibility */
-               char                    oti_mdt_attrs_old[LMA_OLD_SIZE];
+               struct lustre_ost_attrs oti_ost_attrs;
                struct filter_fid_old   oti_ff;
                struct filter_fid       oti_ff_new;
        };
@@ -626,9 +623,9 @@ struct osd_thread_info {
         * cases where a large number of credits are being allocated for
         * single transaction. */
        unsigned int            oti_credits_before;
-       unsigned short          oti_declare_ops[OSD_OT_MAX];
-       unsigned short          oti_declare_ops_cred[OSD_OT_MAX];
-       unsigned short          oti_declare_ops_used[OSD_OT_MAX];
+       unsigned int            oti_declare_ops[OSD_OT_MAX];
+       unsigned int            oti_declare_ops_cred[OSD_OT_MAX];
+       unsigned int            oti_declare_ops_used[OSD_OT_MAX];
 };
 
 extern int ldiskfs_pdo;
@@ -675,7 +672,7 @@ struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
 int osd_ea_fid_set(struct osd_thread_info *info, struct inode *inode,
                   const struct lu_fid *fid, __u32 compat, __u32 incompat);
 int osd_get_lma(struct osd_thread_info *info, struct inode *inode,
-               struct dentry *dentry, struct lustre_mdt_attrs *lma);
+               struct dentry *dentry, struct lustre_ost_attrs *loa);
 void osd_add_oi_cache(struct osd_thread_info *info, struct osd_device *osd,
                      struct osd_inode_id *id, const struct lu_fid *fid);
 int osd_get_idif(struct osd_thread_info *info, struct inode *inode,
@@ -749,14 +746,13 @@ int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
                    struct lquota_id_info *qi, struct osd_object *obj,
                    bool enforce, int *flags);
 int osd_declare_inode_qid(const struct lu_env *env, qid_t uid, qid_t gid,
-                         long long space, struct osd_thandle *oh,
-                         struct osd_object *obj, bool is_blk, int *flags,
-                         bool force);
+                         __u32 projid, long long space, struct osd_thandle *oh,
+                         struct osd_object *obj, int *flags,
+                         enum osd_qid_declare_flags);
 const struct dt_rec *osd_quota_pack(struct osd_object *obj,
                                    const struct dt_rec *rec,
                                    union lquota_rec *quota_rec);
 void osd_quota_unpack(struct osd_object *obj, const struct dt_rec *rec);
-int osd_quota_migration(const struct lu_env *env, struct dt_object *dt);
 
 #ifndef HAVE_I_UID_READ
 static inline uid_t i_uid_read(const struct inode *inode)
@@ -780,11 +776,49 @@ static inline void i_gid_write(struct inode *inode, gid_t gid)
 }
 #endif
 
+#ifdef HAVE_PROJECT_QUOTA
+static inline __u32 i_projid_read(struct inode *inode)
+{
+       return (__u32)from_kprojid(&init_user_ns, LDISKFS_I(inode)->i_projid);
+}
+
+static inline void i_projid_write(struct inode *inode, __u32 projid)
+{
+       kprojid_t kprojid;
+       kprojid = make_kprojid(&init_user_ns, (projid_t)projid);
+       LDISKFS_I(inode)->i_projid = kprojid;
+}
+#else
+static inline uid_t i_projid_read(struct inode *inode)
+{
+       return 0;
+}
+static inline void i_projid_write(struct inode *inode, __u32 projid)
+{
+       return;
+}
+#endif
+
+#ifdef HAVE_LDISKFS_INFO_JINODE
+# define osd_attach_jinode(inode) ldiskfs_inode_attach_jinode(inode)
+#else  /* HAVE_LDISKFS_INFO_JINODE */
+# define osd_attach_jinode(inode) 0
+#endif /* HAVE_LDISKFS_INFO_JINODE */
+
 #ifdef LDISKFS_HT_MISC
 # define osd_journal_start_sb(sb, type, nblock) \
                ldiskfs_journal_start_sb(sb, type, nblock)
-# define osd_ldiskfs_append(handle, inode, nblock) \
-               ldiskfs_append(handle, inode, nblock)
+static inline struct buffer_head *osd_ldiskfs_append(handle_t *handle,
+                                                    struct inode *inode,
+                                                    ldiskfs_lblk_t *nblock)
+{
+       int rc;
+
+       rc = osd_attach_jinode(inode);
+       if (rc)
+               return ERR_PTR(rc);
+       return ldiskfs_append(handle, inode, nblock);
+}
 # define osd_ldiskfs_find_entry(dir, name, de, inlined, lock) \
                (__ldiskfs_find_entry(dir, name, de, inlined, lock) ?: \
                 ERR_PTR(-ENOENT))
@@ -897,6 +931,27 @@ static inline struct super_block *osd_sb(const struct osd_device *dev)
        return dev->od_mnt->mnt_sb;
 }
 
+static inline const char *osd_dev2name(const struct osd_device *dev)
+{
+       return osd_sb(dev)->s_id;
+}
+
+static inline const char *osd_ino2name(const struct inode *inode)
+{
+       return inode->i_sb->s_id;
+}
+
+/**
+ * Put the osd object once done with it.
+ *
+ * \param obj osd object that needs to be put
+ */
+static inline void osd_object_put(const struct lu_env *env,
+                                 struct osd_object *obj)
+{
+       dt_object_put(env, &obj->oo_dt);
+}
+
 static inline int osd_object_is_root(const struct osd_object *obj)
 {
         return osd_sb(osd_obj2dev(obj))->s_root->d_inode == obj->oo_inode;
@@ -930,7 +985,7 @@ static inline struct seq_server_site *osd_seq_site(struct osd_device *osd)
 
 static inline char *osd_name(struct osd_device *osd)
 {
-       return osd->od_dt_dev.dd_lu_dev.ld_obd->obd_name;
+       return osd->od_svname;
 }
 
 static inline bool osd_is_ea_inode(struct inode *inode)
@@ -1008,7 +1063,7 @@ void osd_trans_dump_creds(const struct lu_env *env, struct thandle *th);
 
 static inline void osd_trans_declare_op(const struct lu_env *env,
                                        struct osd_thandle *oh,
-                                       unsigned int op, int credits)
+                                       enum osd_op_type op, int credits)
 {
        struct osd_thread_info *oti = osd_oti_get(env);
 
@@ -1029,7 +1084,8 @@ static inline void osd_trans_declare_op(const struct lu_env *env,
 }
 
 static inline void osd_trans_exec_op(const struct lu_env *env,
-                                    struct thandle *th, unsigned int op)
+                                    struct thandle *th,
+                                    enum osd_op_type op)
 {
        struct osd_thread_info *oti = osd_oti_get(env);
        struct osd_thandle     *oh  = container_of(th, struct osd_thandle,
@@ -1041,8 +1097,9 @@ static inline void osd_trans_exec_op(const struct lu_env *env,
                if (unlikely(ldiskfs_track_declares_assert))
                        LASSERT(op < OSD_OT_MAX);
                else {
-                       CWARN("%s: Invalid operation index %d\n",
-                             osd_name(osd_dt_dev(oh->ot_super.th_dev)), op);
+                       CWARN("%s: opcode %u: invalid value >= %u\n",
+                             osd_name(osd_dt_dev(oh->ot_super.th_dev)),
+                             op, OSD_OT_MAX);
                        libcfs_debug_dumpstack(NULL);
                        return;
                }
@@ -1066,11 +1123,10 @@ static inline void osd_trans_exec_op(const struct lu_env *env,
                if (op == OSD_OT_REF_ADD &&
                    oti->oti_declare_ops_cred[OSD_OT_DESTROY] > 0)
                        goto proceed;
+               CWARN("%s: opcode %u: credits = 0, rollback = %u\n",
+                     osd_name(osd_dt_dev(oh->ot_super.th_dev)), op, rb);
                osd_trans_dump_creds(env, th);
-               CERROR("%s: op = %d, rb = %d\n",
-                      osd_name(osd_dt_dev(oh->ot_super.th_dev)), op, rb);
-               if (unlikely(ldiskfs_track_declares_assert))
-                       LBUG();
+               LASSERT(!ldiskfs_track_declares_assert);
        }
 
 proceed:
@@ -1078,24 +1134,23 @@ proceed:
        oti->oti_credits_before = oh->ot_handle->h_buffer_credits;
        left = oti->oti_declare_ops_cred[op] - oti->oti_declare_ops_used[op];
        if (unlikely(oti->oti_credits_before < left)) {
+               CWARN("%s: opcode %u: before %u < left %u, rollback = %u\n",
+                     osd_name(osd_dt_dev(oh->ot_super.th_dev)), op,
+                     oti->oti_credits_before, left, rb);
                osd_trans_dump_creds(env, th);
-               CERROR("%s: op = %d, rb = %d\n",
-                      osd_name(osd_dt_dev(oh->ot_super.th_dev)), op, rb);
                /* on a very small fs (testing?) it's possible that
                 * the transaction can't fit 1/4 of journal, so we
                 * just request less credits (see osd_trans_start()).
                 * ignore the same case here */
                rb = osd_transaction_size(osd_dt_dev(th->th_dev));
-               if (unlikely(oh->ot_credits < rb)) {
-                       if (unlikely(ldiskfs_track_declares_assert))
-                               LBUG();
-               }
+               if (unlikely(oh->ot_credits < rb))
+                       LASSERT(!ldiskfs_track_declares_assert);
        }
 }
 
 static inline void osd_trans_exec_check(const struct lu_env *env,
                                        struct thandle *th,
-                                       unsigned int op)
+                                       enum osd_op_type op)
 {
        struct osd_thread_info *oti = osd_oti_get(env);
        struct osd_thandle     *oh  = container_of(th, struct osd_thandle,
@@ -1135,8 +1190,9 @@ static inline void osd_trans_exec_check(const struct lu_env *env,
                oti->oti_declare_ops_used[OSD_OT_QUOTA] += over;
                oti->oti_declare_ops_used[op] -= over;
        } else {
-               CWARN("op %d: used %u, used now %u, reserved %u\n",
-                     op, oti->oti_declare_ops_used[op], used,
+               CWARN("%s: opcode %d: used %u, used now %u, reserved %u\n",
+                     osd_name(osd_dt_dev(oh->ot_super.th_dev)), op,
+                     oti->oti_declare_ops_used[op], used,
                      oti->oti_declare_ops_cred[op]);
                osd_trans_dump_creds(env, th);
                if (unlikely(ldiskfs_track_declares_assert))
@@ -1185,7 +1241,7 @@ int osd_acct_obj_lookup(struct osd_thread_info *info, struct osd_device *osd,
 static inline int is_32bit_api(void)
 {
 #ifdef CONFIG_COMPAT
-       return is_compat_task();
+       return in_compat_syscall();
 #else
        return (BITS_PER_LONG == 32);
 #endif
@@ -1220,18 +1276,23 @@ static inline struct buffer_head *__ldiskfs_bread(handle_t *handle,
                                                  ldiskfs_lblk_t block,
                                                  int create)
 {
-#ifdef HAVE_EXT4_BREAD_4ARGS
-       return ldiskfs_bread(handle, inode, block, create);
-#else
+       int rc = 0;
        struct buffer_head *bh;
-       int error = 0;
 
-       bh = ldiskfs_bread(handle, inode, block, create, &error);
-       if (bh == NULL && error != 0)
-               bh = ERR_PTR(error);
+       if (create) {
+               rc = osd_attach_jinode(inode);
+               if (rc)
+                       return ERR_PTR(rc);
+       }
+#ifdef HAVE_EXT4_BREAD_4ARGS
+       bh = ldiskfs_bread(handle, inode, block, create);
+#else
 
-       return bh;
+       bh = ldiskfs_bread(handle, inode, block, create, &rc);
+       if (bh == NULL && rc != 0)
+               bh = ERR_PTR(rc);
 #endif
+       return bh;
 }
 
 void ldiskfs_inc_count(handle_t *handle, struct inode *inode);
@@ -1239,4 +1300,5 @@ void ldiskfs_dec_count(handle_t *handle, struct inode *inode);
 
 void osd_fini_iobuf(struct osd_device *d, struct osd_iobuf *iobuf);
 
+
 #endif /* _OSD_INTERNAL_H */