* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2012, Whamcloud, Inc.
+ * Copyright (c) 2011, 2012, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
#include <obd_class.h>
#include <lustre_disk.h>
#include <dt_object.h>
-#include <lquota.h>
+#include <lustre_quota.h>
#include "osd_oi.h"
#include "osd_iam.h"
/** Enable thandle usage statistics */
#define OSD_THANDLE_STATS (0)
-#ifdef HAVE_QUOTA_SUPPORT
-struct osd_ctxt {
- __u32 oc_uid;
- __u32 oc_gid;
- cfs_kernel_cap_t oc_cap;
-};
-#endif
-
struct osd_directory {
struct iam_container od_container;
struct iam_descr od_descr;
* to protect index ops.
*/
struct htree_lock_head *oo_hl_head;
- cfs_rw_semaphore_t oo_ext_idx_sem;
- cfs_rw_semaphore_t oo_sem;
- struct osd_directory *oo_dir;
- /** protects inode attributes. */
- cfs_spinlock_t oo_guard;
+ struct rw_semaphore oo_ext_idx_sem;
+ struct rw_semaphore oo_sem;
+ struct osd_directory *oo_dir;
+ /** protects inode attributes. */
+ spinlock_t oo_guard;
/**
* Following two members are used to indicate the presence of dot and
* dotdot in the given directory. This is required for interop mode
#endif
};
-#ifdef HAVE_LDISKFS_PDO
-
-#define osd_ldiskfs_find_entry(dir, dentry, de, lock) \
- ll_ldiskfs_find_entry(dir, dentry, de, lock)
-#define osd_ldiskfs_add_entry(handle, child, cinode, hlock) \
- ldiskfs_add_entry(handle, child, cinode, hlock)
-
-#else /* HAVE_LDISKFS_PDO */
-
-struct htree_lock {
- int dummy;
+struct osd_obj_seq {
+ /* protects on-fly initialization */
+ int oos_subdir_count; /* subdir count for each seq */
+ struct dentry *oos_root; /* O/<seq> */
+ struct dentry **oos_dirs; /* O/<seq>/d0-dXX */
+ obd_seq oos_seq; /* seq number */
+ cfs_list_t oos_seq_list; /* list to seq_list */
};
-struct htree_lock_head {
- int dummy;
+struct osd_obj_map {
+ struct dentry *om_root; /* dentry for /O */
+ rwlock_t om_seq_list_lock; /* lock for seq_list */
+ cfs_list_t om_seq_list; /* list head for seq */
+ int om_subdir_count;
+ struct semaphore om_dir_init_sem;
};
-#define ldiskfs_htree_lock(lock, head, inode, op) do { LBUG(); } while (0)
-#define ldiskfs_htree_unlock(lock) do { LBUG(); } while (0)
-
-static inline struct htree_lock_head *ldiskfs_htree_lock_head_alloc(int dep)
-{
- LBUG();
- return NULL;
-}
-
-#define ldiskfs_htree_lock_head_free(lh) do { LBUG(); } while (0)
-
-#define LDISKFS_DUMMY_HTREE_LOCK 0xbabecafe
-
-static inline struct htree_lock *ldiskfs_htree_lock_alloc(void)
-{
- return (struct htree_lock *)LDISKFS_DUMMY_HTREE_LOCK;
-}
-
-static inline void ldiskfs_htree_lock_free(struct htree_lock *lk)
-{
- LASSERT((unsigned long)lk == LDISKFS_DUMMY_HTREE_LOCK);
-}
-
-#define HTREE_HBITS_DEF 0
-
#define osd_ldiskfs_find_entry(dir, dentry, de, lock) \
- ll_ldiskfs_find_entry(dir, dentry, de)
-#define osd_ldiskfs_add_entry(handle, child, cinode, lock) \
- ldiskfs_add_entry(handle, child, cinode)
-
-#endif /* HAVE_LDISKFS_PDO */
+ ll_ldiskfs_find_entry(dir, dentry, de, lock)
+#define osd_ldiskfs_add_entry(handle, child, cinode, hlock) \
+ ldiskfs_add_entry(handle, child, cinode, hlock)
#define OSD_OTABLE_IT_CACHE_SIZE 128
#define OSD_OTABLE_IT_CACHE_MASK (~(OSD_OTABLE_IT_CACHE_SIZE - 1))
/* super-class */
struct dt_device od_dt_dev;
/* information about underlying file system */
- struct lustre_mount_info *od_mount;
struct vfsmount *od_mnt;
/* object index */
struct osd_oi **od_oi_table;
*/
cfs_time_t od_osfs_age;
struct obd_statfs od_statfs;
- cfs_spinlock_t od_osfs_lock;
+ spinlock_t od_osfs_lock;
- /**
- * The following flag indicates, if it is interop mode or not.
- * It will be initialized, using mount param.
- */
- __u32 od_iop_mode;
+ unsigned int od_noscrub:1;
- struct fsfilt_operations *od_fsops;
+ struct fsfilt_operations *od_fsops;
+ int od_connects;
+ struct lu_site od_site;
- /*
- * mapping for legacy OST objids
- */
- struct osd_compat_objid *od_ost_map;
+ struct osd_obj_map *od_ost_map;
unsigned long long od_readcache_max_filesize;
int od_read_cache;
cfs_atomic_t od_r_in_flight;
cfs_atomic_t od_w_in_flight;
- cfs_mutex_t od_otable_mutex;
+ struct mutex od_otable_mutex;
struct osd_otable_it *od_otable_it;
struct osd_scrub od_scrub;
/* service name associated with the osd device */
char od_svname[MAX_OBD_NAME];
+ char od_mntdev[MAX_OBD_NAME];
/* quota slave instance */
struct qsd_instance *od_quota_slave;
#define OSD_TRACK_DECLARES
#ifdef OSD_TRACK_DECLARES
-#define OSD_DECLARE_OP(oh, op) { \
- LASSERT(oh->ot_handle == NULL); \
- ((oh)->ot_declare_ ##op)++; }
-#define OSD_EXEC_OP(handle,op) { \
- struct osd_thandle *oh; \
- oh = container_of0(handle, struct osd_thandle, ot_super);\
- if (((oh)->ot_declare_ ##op) > 0) { \
- ((oh)->ot_declare_ ##op)--; \
- } \
- }
+#define OSD_DECLARE_OP(oh, op, credits) \
+do { \
+ LASSERT((oh)->ot_handle == NULL); \
+ ((oh)->ot_declare_ ##op)++; \
+ ((oh)->ot_declare_ ##op ##_cred) += (credits); \
+ (oh)->ot_credits += (credits); \
+} while (0)
+#define OSD_EXEC_OP(handle, op) \
+do { \
+ struct osd_thandle *oh = container_of(handle, typeof(*oh), ot_super); \
+ LASSERT((oh)->ot_declare_ ##op > 0); \
+ ((oh)->ot_declare_ ##op)--; \
+} while (0)
#else
-#define OSD_DECLARE_OP(oh, op)
+#define OSD_DECLARE_OP(oh, op, credits) (oh)->ot_credits += (credits)
#define OSD_EXEC_OP(oh, op)
#endif
/* There are at most 10 uid/gids 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 the child
- * is directory);
+ * - 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);
unsigned short ot_id_cnt;
unsigned short ot_id_type;
uid_t ot_id_array[OSD_MAX_UGID_CNT];
+ struct lquota_trans *ot_quota_trans;
#ifdef OSD_TRACK_DECLARES
- unsigned char ot_declare_attr_set;
- unsigned char ot_declare_punch;
- unsigned char ot_declare_xattr_set;
- unsigned char ot_declare_create;
- unsigned char ot_declare_destroy;
- unsigned char ot_declare_ref_add;
- unsigned char ot_declare_ref_del;
- unsigned char ot_declare_write;
- unsigned char ot_declare_insert;
- unsigned char ot_declare_delete;
+ /* Tracking for transaction credits, to allow debugging and optimizing
+ * cases where a large number of credits are being allocated for
+ * single transaction. */
+ unsigned char ot_declare_attr_set;
+ unsigned char ot_declare_punch;
+ unsigned char ot_declare_xattr_set;
+ unsigned char ot_declare_create;
+ unsigned char ot_declare_destroy;
+ unsigned char ot_declare_ref_add;
+ unsigned char ot_declare_ref_del;
+ unsigned char ot_declare_write;
+ unsigned char ot_declare_insert;
+ unsigned char ot_declare_delete;
+ unsigned char ot_declare_quota;
+
+ unsigned short ot_declare_attr_set_cred;
+ unsigned short ot_declare_punch_cred;
+ unsigned short ot_declare_xattr_set_cred;
+ unsigned short ot_declare_create_cred;
+ unsigned short ot_declare_destroy_cred;
+ unsigned short ot_declare_ref_add_cred;
+ unsigned short ot_declare_ref_del_cred;
+ unsigned short ot_declare_write_cred;
+ unsigned short ot_declare_insert_cred;
+ unsigned short ot_declare_delete_cred;
+ unsigned short ot_declare_quota_cred;
#endif
#if OSD_THANDLE_STATS
struct iam_iterator oi_it;
};
+struct osd_quota_leaf {
+ cfs_list_t oql_link;
+ uint oql_blk;
+};
+
/**
* Iterator's in-memory data structure for quota file.
*/
struct osd_it_quota {
struct osd_object *oiq_obj;
/** tree blocks path to where the entry is stored */
- uint oiq_blk[LUSTRE_DQTREEDEPTH];
+ uint oiq_blk[LUSTRE_DQTREEDEPTH + 1];
/** on-disk offset for current key where quota record can be found */
loff_t oiq_offset;
/** identifier for current quota record */
__u64 oiq_id;
+ /** the record index in the leaf/index block */
+ uint oiq_index[LUSTRE_DQTREEDEPTH + 1];
+ /** list of already processed leaf blocks */
+ cfs_list_t oiq_list;
};
#define MAX_BLOCKS_PER_PAGE (CFS_PAGE_SIZE / 512)
unsigned long dr_start_time;
unsigned long dr_elapsed; /* how long io took */
struct osd_device *dr_dev;
+ unsigned int dr_init_at; /* the line iobuf was initialized */
};
struct osd_thread_info {
/** used in osd_fid_set() to put xattr */
struct lu_buf oti_buf;
/** used in osd_ea_fid_set() to set fid into common ea */
- struct lustre_mdt_attrs oti_mdt_attrs;
+ union {
+ struct lustre_mdt_attrs oti_mdt_attrs;
+ /* old LMA for compatibility */
+ char oti_mdt_attrs_old[LMA_OLD_SIZE];
+ };
/** 0-copy IO */
struct osd_iobuf oti_iobuf;
struct inode oti_inode;
int oti_created[PTLRPC_MAX_BRW_PAGES];
-#ifdef HAVE_QUOTA_SUPPORT
- struct osd_ctxt oti_ctxt;
-#endif
struct lu_env oti_obj_delete_tx_env;
#define OSD_FID_REC_SZ 32
char oti_ldp[OSD_FID_REC_SZ];
struct if_dqblk oti_dqblk;
struct if_dqinfo oti_dqinfo;
};
+ struct lquota_id_info oti_qi;
+ struct lquota_trans oti_quota_trans;
+ union lquota_rec oti_quota_rec;
+ __u64 oti_quota_id;
};
extern int ldiskfs_pdo;
void lprocfs_osd_init_vars(struct lprocfs_static_vars *lvars);
int osd_procfs_init(struct osd_device *osd, const char *name);
int osd_procfs_fini(struct osd_device *osd);
-void osd_lprocfs_time_start(const struct lu_env *env);
-void osd_lprocfs_time_end(const struct lu_env *env,
- struct osd_device *osd, int op);
void osd_brw_stats_update(struct osd_device *osd, struct osd_iobuf *iobuf);
#endif
struct obd_statfs *sfs);
int osd_object_auth(const struct lu_env *env, struct dt_object *dt,
struct lustre_capa *capa, __u64 opc);
-void osd_declare_qid(struct dt_object *dt, struct osd_thandle *oh,
- int type, uid_t id, struct inode *inode);
struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
struct osd_inode_id *id);
struct inode *osd_iget_fid(struct osd_thread_info *info, struct osd_device *dev,
struct osd_inode_id *id, struct lu_fid *fid);
-int osd_compat_init(struct osd_device *dev);
-void osd_compat_fini(struct osd_device *dev);
-int osd_compat_objid_lookup(struct osd_thread_info *info,
- struct osd_device *osd,
- const struct lu_fid *fid, struct osd_inode_id *id);
-int osd_compat_objid_insert(struct osd_thread_info *info,
- struct osd_device *osd,
- const struct lu_fid *fid,
- const struct osd_inode_id *id, struct thandle *th);
-int osd_compat_objid_delete(struct osd_thread_info *info,
- struct osd_device *osd,
- const struct lu_fid *fid, struct thandle *th);
-int osd_compat_spec_lookup(struct osd_thread_info *info,
- struct osd_device *osd,
- const struct lu_fid *fid, struct osd_inode_id *id);
-int osd_compat_spec_insert(struct osd_thread_info *info,
- struct osd_device *osd,
- const struct lu_fid *fid,
- const struct osd_inode_id *id, struct thandle *th);
+int osd_obj_map_init(struct osd_device *osd);
+void osd_obj_map_fini(struct osd_device *dev);
+int osd_obj_map_lookup(struct osd_thread_info *info, struct osd_device *osd,
+ const struct lu_fid *fid, struct osd_inode_id *id);
+int osd_obj_map_insert(struct osd_thread_info *info, struct osd_device *osd,
+ const struct lu_fid *fid, const struct osd_inode_id *id,
+ struct thandle *th);
+int osd_obj_map_delete(struct osd_thread_info *info, struct osd_device *osd,
+ const struct lu_fid *fid, struct thandle *th);
+int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd,
+ const struct lu_fid *fid, struct osd_inode_id *id);
+int osd_obj_spec_insert(struct osd_thread_info *info, struct osd_device *osd,
+ const struct lu_fid *fid, const struct osd_inode_id *id,
+ struct thandle *th);
void osd_scrub_file_reset(struct osd_scrub *scrub, __u8 *uuid, __u64 flags);
int osd_scrub_file_store(struct osd_scrub *scrub);
struct osd_object *obj, int type,
qid_t dqid, uint blk, int depth,
struct osd_it_quota *it);
+/* osd_quota.c */
+int osd_declare_qid(const struct lu_env *env, struct osd_thandle *oh,
+ struct lquota_id_info *qi, bool allocated, 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,
+ bool is_blk, bool allocated, int *flags, bool force);
+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,
+ const struct dt_index_features *feat);
+
+static inline bool is_quota_glb_feat(const struct dt_index_features *feat)
+{
+ return (feat == &dt_quota_iusr_features ||
+ feat == &dt_quota_busr_features ||
+ feat == &dt_quota_igrp_features ||
+ feat == &dt_quota_bgrp_features) ? true : false;
+}
+
/*
* Invariants, assertions.
*/
#define osd_invariant(obj) (1)
#endif
+#define OSD_MAX_CACHE_SIZE OBD_OBJECT_EOF
+
extern const struct dt_index_operations osd_otable_ops;
static inline int osd_oi_fid2idx(struct osd_device *dev,
const struct lu_fid *fid)
{
LASSERTF(!fid_is_idif(fid), DFID"\n", PFID(fid));
+ LASSERTF(!fid_is_last_id(fid), DFID"\n", PFID(fid));
LASSERTF(!fid_is_igif(fid), DFID"\n", PFID(fid));
LASSERT(osd->od_oi_table != NULL && osd->od_oi_count >= 1);
/* It can work even od_oi_count equals to 1 although it's unexpected,
static inline struct super_block *osd_sb(const struct osd_device *dev)
{
- return dev->od_mount->lmi_mnt->mnt_sb;
+ return dev->od_mnt->mnt_sb;
}
static inline int osd_object_is_root(const struct osd_object *obj)
return LDISKFS_SB(osd_sb(dev))->s_journal;
}
+static inline struct seq_server_site *osd_seq_site(struct osd_device *osd)
+{
+ return osd->od_dt_dev.dd_lu_dev.ld_site->ld_seq_site;
+}
+
+static inline char *osd_name(struct osd_device *osd)
+{
+ return osd->od_dt_dev.dd_lu_dev.ld_obd->obd_name;
+}
+
+
extern const struct dt_body_operations osd_body_ops;
extern struct lu_context_key osd_key;
int osd_ldiskfs_read(struct inode *inode, void *buf, int size, loff_t *offs);
int osd_ldiskfs_write_record(struct inode *inode, void *buf, int bufsize,
- loff_t *offs, handle_t *handle);
+ int write_NUL, loff_t *offs, handle_t *handle);
static inline
struct dentry *osd_child_dentry_by_inode(const struct lu_env *env,