#include <uapi/linux/lustre/lustre_idl.h>
#include <lu_ref.h>
#include <linux/percpu_counter.h>
+#include <linux/ctype.h>
+#include <obd_target.h>
struct seq_file;
struct proc_dir_entry;
struct lu_object_header;
struct lu_context;
struct lu_env;
+struct lu_name;
/**
* Operations common for data and meta-data devices.
struct lu_device *parent,
struct lu_device *dev);
+
+ /**
+ * Allocate new FID for file with @name under @parent
+ *
+ * \param[in] env execution environment for this thread
+ * \param[in] dev dt device
+ * \param[out] fid new FID allocated
+ * \param[in] parent parent object
+ * \param[in] name lu_name
+ *
+ * \retval 0 on success
+ * \retval 0 0 FID allocated successfully.
+ * \retval 1 1 FID allocated successfully and new sequence
+ * requested from seq meta server
+ * \retval negative negative errno if FID allocation failed.
+ */
+ int (*ldo_fid_alloc)(const struct lu_env *env,
+ struct lu_device *dev,
+ struct lu_fid *fid,
+ struct lu_object *parent,
+ const struct lu_name *name);
};
/**
*/
void (*loo_object_delete)(const struct lu_env *env,
struct lu_object *o);
- /**
- * Dual to lu_device_operations::ldo_object_alloc(). Called when
- * object is removed from memory.
- */
- void (*loo_object_free)(const struct lu_env *env,
- struct lu_object *o);
+ /**
+ * Dual to lu_device_operations::ldo_object_alloc(). Called when
+ * object is removed from memory. Must use call_rcu or kfree_rcu
+ * if the object contains an lu_object_header.
+ */
+ void (*loo_object_free)(const struct lu_env *env,
+ struct lu_object *o);
/**
* Called when last active reference to the object is released (and
* object returns to the cache). This method is optional.
* device types.
*/
enum lu_device_tag {
- /** this is meta-data device */
- LU_DEVICE_MD = (1 << 0),
- /** this is data device */
- LU_DEVICE_DT = (1 << 1),
- /** data device in the client stack */
- LU_DEVICE_CL = (1 << 2)
+ /** this is meta-data device */
+ LU_DEVICE_MD = BIT(0),
+ /** this is data device */
+ LU_DEVICE_DT = BIT(1),
+ /** data device in the client stack */
+ LU_DEVICE_CL = BIT(2)
};
/**
*
* \see enum la_valid
*/
- __u64 la_valid;
+ __u64 la_valid;
/** size in bytes */
- __u64 la_size;
+ __u64 la_size;
/** modification time in seconds since Epoch */
s64 la_mtime;
/** access time in seconds since Epoch */
s64 la_atime;
/** change time in seconds since Epoch */
s64 la_ctime;
+ /** create time in seconds since Epoch */
+ s64 la_btime;
/** 512-byte blocks allocated to object */
- __u64 la_blocks;
+ __u64 la_blocks;
/** permission bits and file type */
- __u32 la_mode;
+ __u32 la_mode;
/** owner id */
- __u32 la_uid;
+ __u32 la_uid;
/** group id */
- __u32 la_gid;
+ __u32 la_gid;
/** object flags */
- __u32 la_flags;
+ __u32 la_flags;
/** number of persistent references to this object */
- __u32 la_nlink;
+ __u32 la_nlink;
/** blk bits of the object*/
- __u32 la_blkbits;
+ __u32 la_blkbits;
/** blk size of the object*/
- __u32 la_blksize;
+ __u32 la_blksize;
/** real device */
- __u32 la_rdev;
+ __u32 la_rdev;
/** project id */
- __u32 la_projid;
+ __u32 la_projid;
/** set layout version to OST objects. */
__u32 la_layout_version;
+ /** dirent count */
+ __u64 la_dirent_count;
};
+#define LU_DIRENT_COUNT_UNSET ~0ULL
+
/**
* Layer in the layered object.
*/
* Object is initialized, when object is found in cache, it may not be
* intialized yet, the object allocator will initialize it.
*/
- LU_OBJECT_INITED = 2
+ LU_OBJECT_INITED = 2,
+ /**
+ * Object is being purged, so mustn't be returned by
+ * htable_lookup()
+ */
+ LU_OBJECT_PURGING = 3,
};
enum lu_object_header_attr {
- LOHA_EXISTS = 1 << 0,
- LOHA_REMOTE = 1 << 1,
- LOHA_HAS_AGENT_ENTRY = 1 << 2,
+ LOHA_EXISTS = BIT(0),
+ LOHA_REMOTE = BIT(1),
+ LOHA_HAS_AGENT_ENTRY = BIT(2),
/**
* UNIX file type is stored in S_IFMT bits.
*/
* A list of references to this object, for debugging.
*/
struct lu_ref loh_reference;
+ /*
+ * Handle used for kfree_rcu() or similar.
+ */
+ struct rcu_head loh_rcu;
};
struct fld;
* objects hash table
*/
struct cfs_hash *ls_obj_hash;
+ /*
+ * buckets for summary data
+ */
+ struct lu_site_bkt_data *ls_bkts;
+ int ls_bkt_cnt;
+ u32 ls_bkt_seed;
/**
* index of bucket on hash table while purging
*/
};
enum lu_xattr_flags {
- LU_XATTR_REPLACE = (1 << 0),
- LU_XATTR_CREATE = (1 << 1),
- LU_XATTR_MERGE = (1 << 2),
- LU_XATTR_SPLIT = (1 << 3),
+ LU_XATTR_REPLACE = BIT(0),
+ LU_XATTR_CREATE = BIT(1),
+ LU_XATTR_MERGE = BIT(2),
+ LU_XATTR_SPLIT = BIT(3),
};
/** @} helpers */
*/
enum lu_context_tag {
- /**
- * Thread on md server
- */
- LCT_MD_THREAD = 1 << 0,
- /**
- * Thread on dt server
- */
- LCT_DT_THREAD = 1 << 1,
- /**
- * Thread on client
- */
- LCT_CL_THREAD = 1 << 3,
- /**
- * A per-request session on a server, and a per-system-call session on
- * a client.
- */
- LCT_SESSION = 1 << 4,
- /**
- * A per-request data on OSP device
- */
- LCT_OSP_THREAD = 1 << 5,
- /**
- * MGS device thread
- */
- LCT_MG_THREAD = 1 << 6,
- /**
- * Context for local operations
- */
- LCT_LOCAL = 1 << 7,
+ /**
+ * Thread on md server
+ */
+ LCT_MD_THREAD = BIT(0),
+ /**
+ * Thread on dt server
+ */
+ LCT_DT_THREAD = BIT(1),
+ /**
+ * Thread on client
+ */
+ LCT_CL_THREAD = BIT(3),
+ /**
+ * A per-request session on a server, and a per-system-call session on
+ * a client.
+ */
+ LCT_SESSION = BIT(4),
+ /**
+ * A per-request data on OSP device
+ */
+ LCT_OSP_THREAD = BIT(5),
+ /**
+ * MGS device thread
+ */
+ LCT_MG_THREAD = BIT(6),
+ /**
+ * Context for local operations
+ */
+ LCT_LOCAL = BIT(7),
/**
* session for server thread
**/
- LCT_SERVER_SESSION = 1 << 8,
- /**
- * Set when at least one of keys, having values in this context has
- * non-NULL lu_context_key::lct_exit() method. This is used to
- * optimize lu_context_exit() call.
- */
- LCT_HAS_EXIT = 1 << 28,
- /**
- * Don't add references for modules creating key values in that context.
- * This is only for contexts used internally by lu_object framework.
- */
- LCT_NOREF = 1 << 29,
- /**
- * Key is being prepared for retiring, don't create new values for it.
- */
- LCT_QUIESCENT = 1 << 30,
- /**
- * Context should be remembered.
- */
- LCT_REMEMBER = 1 << 31,
- /**
- * Contexts usable in cache shrinker thread.
- */
- LCT_SHRINKER = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD|LCT_NOREF
+ LCT_SERVER_SESSION = BIT(8),
+ /**
+ * Set when at least one of keys, having values in this context has
+ * non-NULL lu_context_key::lct_exit() method. This is used to
+ * optimize lu_context_exit() call.
+ */
+ LCT_HAS_EXIT = BIT(28),
+ /**
+ * Don't add references for modules creating key values in that context.
+ * This is only for contexts used internally by lu_object framework.
+ */
+ LCT_NOREF = BIT(29),
+ /**
+ * Key is being prepared for retiring, don't create new values for it.
+ */
+ LCT_QUIESCENT = BIT(30),
+ /**
+ * Context should be remembered.
+ */
+ LCT_REMEMBER = BIT(31),
+ /**
+ * Contexts usable in cache shrinker thread.
+ */
+ LCT_SHRINKER = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD|LCT_NOREF,
};
/**
struct lu_env *lu_env_find(void);
int lu_env_add(struct lu_env *env);
+int lu_env_add_task(struct lu_env *env, struct task_struct *task);
void lu_env_remove(struct lu_env *env);
/** @} lu_context */
return name_is_dot_or_dotdot(lname->ln_name, lname->ln_namelen);
}
+static inline bool lu_name_is_temp_file(const char *name, int namelen,
+ bool dot_prefix, int suffixlen)
+{
+ int lower = 0;
+ int upper = 0;
+ int digit = 0;
+ int len = suffixlen;
+
+ if (dot_prefix && name[0] != '.')
+ return false;
+
+ if (namelen < dot_prefix + suffixlen + 2 ||
+ name[namelen - suffixlen - 1] != '.')
+ return false;
+
+ while (len) {
+ lower += islower(name[namelen - len]);
+ upper += isupper(name[namelen - len]);
+ digit += isdigit(name[namelen - len]);
+ len--;
+ }
+ /* mktemp() filename suffixes will have a mix of upper- and lower-case
+ * letters and/or numbers, not all numbers, or all upper or lower-case.
+ * About 0.07% of randomly-generated names will slip through,
+ * but this avoids 99.93% of cross-MDT renames for those files.
+ */
+ if ((digit >= suffixlen - 1 && !isdigit(name[namelen - suffixlen])) ||
+ upper == suffixlen || lower == suffixlen)
+ return false;
+
+ return true;
+}
+
+static inline bool lu_name_is_backup_file(const char *name, int namelen,
+ int *suffixlen)
+{
+ if (namelen > 1 &&
+ name[namelen - 2] != '.' && name[namelen - 1] == '~') {
+ if (suffixlen)
+ *suffixlen = 1;
+ return true;
+ }
+
+ if (namelen > 4 && name[namelen - 4] == '.' &&
+ (!strncasecmp(name + namelen - 3, "bak", 3) ||
+ !strncasecmp(name + namelen - 3, "sav", 3))) {
+ if (suffixlen)
+ *suffixlen = 4;
+ return true;
+ }
+
+ if (namelen > 5 && name[namelen - 5] == '.' &&
+ !strncasecmp(name + namelen - 4, "orig", 4)) {
+ if (suffixlen)
+ *suffixlen = 5;
+ return true;
+ }
+
+ return false;
+}
+
static inline bool lu_name_is_valid_len(const char *name, size_t name_len)
{
return name != NULL &&
return lu_device_is_cl(o->lo_dev);
}
-/* Generic subset of tgts */
-struct lu_tgt_pool {
- __u32 *op_array; /* array of index of
- * lov_obd->lov_tgts */
- unsigned int op_count; /* number of tgts in the array */
- unsigned int op_size; /* allocated size of op_array */
- struct rw_semaphore op_rw_sem; /* to protect lu_tgt_pool use */
-};
-
/* round-robin QoS data for LOD/LMV */
struct lu_qos_rr {
spinlock_t lqr_alloc; /* protect allocation index */
__u32 ltd_index;
__u32 ltd_gen;
struct list_head ltd_kill;
- struct ptlrpc_thread *ltd_recovery_thread;
+ struct task_struct *ltd_recovery_task;
struct mutex ltd_fid_mutex;
struct lu_tgt_qos ltd_qos; /* qos info per target */
struct obd_statfs ltd_statfs;