#define MDS_OPEN_NORESTORE 0100000000000ULL /* Do not restore file at open */
#define MDS_OPEN_NEWSTRIPE 0200000000000ULL /* New stripe needed (restripe or
* hsm restore) */
+#define MDS_OPEN_VOLATILE 0400000000000ULL /* File is volatile = created
+ unlinked */
/* permission for create non-directory file */
#define MAY_CREATE (1 << 7)
#define MAY_RGETFACL (1 << 14)
enum {
- MDS_CHECK_SPLIT = 1 << 0,
- MDS_CROSS_REF = 1 << 1,
- MDS_VTX_BYPASS = 1 << 2,
- MDS_PERM_BYPASS = 1 << 3,
- MDS_SOM = 1 << 4,
- MDS_QUOTA_IGNORE = 1 << 5,
- MDS_CLOSE_CLEANUP = 1 << 6,
- MDS_KEEP_ORPHAN = 1 << 7,
- MDS_RECOV_OPEN = 1 << 8,
- MDS_DATA_MODIFIED = 1 << 9,
+ MDS_CHECK_SPLIT = 1 << 0,
+ MDS_CROSS_REF = 1 << 1,
+ MDS_VTX_BYPASS = 1 << 2,
+ MDS_PERM_BYPASS = 1 << 3,
+ MDS_SOM = 1 << 4,
+ MDS_QUOTA_IGNORE = 1 << 5,
+ MDS_CLOSE_CLEANUP = 1 << 6,
+ MDS_KEEP_ORPHAN = 1 << 7,
+ MDS_RECOV_OPEN = 1 << 8,
+ MDS_DATA_MODIFIED = 1 << 9,
+ MDS_CREATE_VOLATILE = 1 << 10,
};
/* instance of mdt_reint_rec */
#endif /* !__KERNEL__ */
+/* lustre volatile file support
+ * file name header: .^L^S^T^R:volatile"
+ */
+#define LUSTRE_VOLATILE_HDR ".\x0c\x13\x14\x12:VOLATILE"
+#define LUSTRE_VOLATILE_HDR_LEN 14
+/* hdr + MDT index */
+#define LUSTRE_VOLATILE_IDX LUSTRE_VOLATILE_HDR":%.4X:"
+
typedef enum lustre_quota_version {
LUSTRE_QUOTA_V2 = 1
} lustre_quota_version_t;
extern int llapi_get_obd_count(char *mnt, int *count, int is_mdt);
extern int parse_size(char *optarg, unsigned long long *size,
unsigned long long *size_units, int bytes_spec);
-extern int llapi_path2fid(const char *path, lustre_fid *fid);
extern int llapi_search_mounts(const char *pathname, int index,
char *mntdir, char *fsname);
extern int llapi_search_fsname(const char *pathname, char *fsname);
extern int llapi_quotacheck(char *mnt, int check_type);
extern int llapi_poll_quotacheck(char *mnt, struct if_quotacheck *qchk);
extern int llapi_quotactl(char *mnt, struct if_quotactl *qctl);
-extern int llapi_target_iterate(int type_num, char **obd_type, void *args, llapi_cb_t cb);
+extern int llapi_target_iterate(int type_num, char **obd_type, void *args,
+ llapi_cb_t cb);
extern int llapi_get_connect_flags(const char *mnt, __u64 *flags);
extern int llapi_lsetfacl(int argc, char *argv[]);
extern int llapi_lgetfacl(int argc, char *argv[]);
extern int llapi_cp(int argc, char *argv[]);
extern int llapi_ls(int argc, char *argv[]);
extern int llapi_fid2path(const char *device, const char *fidstr, char *path,
- int pathlen, long long *recno, int *linkno);
+ int pathlen, long long *recno, int *linkno);
extern int llapi_path2fid(const char *path, lustre_fid *fid);
-extern int llapi_get_version(char *buffer, int buffer_size, char **version);
+extern int llapi_fd2fid(const int fd, lustre_fid *fid);
+extern int llapi_get_version(char *buffer, int buffer_size, char **version);
extern int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags);
+extern int llapi_create_volatile_idx(char *directory, int idx, int mode);
+static inline int llapi_create_volatile(char *directory, int mode)
+{
+ return llapi_create_volatile_idx(directory, -1, mode);
+}
+
+
/* Changelog interface. priv is private state, managed internally
by these functions */
#define CHANGELOG_FLAG_FOLLOW 0x01 /* Not yet implemented */
return lu_dev->ld_obd->obd_name;
}
+static inline bool filename_is_volatile(const char *name, int namelen, int *idx)
+{
+ const char *start;
+ char *end;
+
+ if (strncmp(name, LUSTRE_VOLATILE_HDR, LUSTRE_VOLATILE_HDR_LEN) != 0)
+ return false;
+
+ /* caller does not care of idx */
+ if (idx == NULL)
+ return true;
+
+ /* volatile file, the MDT can be set from name */
+ /* name format is LUSTRE_VOLATILE_HDR:[idx]: */
+ /* if no MDT is specified, use std way */
+ if (namelen < LUSTRE_VOLATILE_HDR_LEN + 2)
+ goto bad_format;
+ /* test for no MDT idx case */
+ if ((*(name + LUSTRE_VOLATILE_HDR_LEN) == ':') &&
+ (*(name + LUSTRE_VOLATILE_HDR_LEN + 1) == ':')) {
+ *idx = -1;
+ return true;
+ }
+ /* we have an idx, read it */
+ start = name + LUSTRE_VOLATILE_HDR_LEN + 1;
+ *idx = strtoul(start, &end, 0);
+ /* error cases:
+ * no digit, no trailing :, negative value
+ */
+ if (((*idx == 0) && (end == start)) ||
+ (*end != ':') || (*idx < 0))
+ goto bad_format;
+
+ return true;
+bad_format:
+ /* bad format of mdt idx, we cannot return an error
+ * to caller so we use hash algo */
+ CERROR("Bad volatile file name format: %s\n",
+ name + LUSTRE_VOLATILE_HDR_LEN);
+ return false;
+}
+
#endif /* __OBD_H */
/* for writepage() only to communicate to fsync */
int f_async_rc;
+ /* volatile file criteria is based on file name, this
+ * flag is used to keep the test result, so the strcmp
+ * is done only once
+ */
+ bool f_volatile;
/*
* whenever a process try to read/write the file, the
* jobid of the process will be saved here, and it'll
#define lli_agl_index u.f.f_agl_index
#define lli_async_rc u.f.f_async_rc
#define lli_jobid u.f.f_jobid
+#define lli_volatile u.f.f_volatile
} u;
CFS_INIT_LIST_HEAD(&lli->lli_agl_list);
lli->lli_agl_index = 0;
lli->lli_async_rc = 0;
+ lli->lli_volatile = false;
}
mutex_init(&lli->lli_layout_mutex);
}
op_data->op_fsgid = cfs_curproc_fsgid();
op_data->op_cap = cfs_curproc_cap_pack();
op_data->op_bias = 0;
+ if ((opc == LUSTRE_OPC_CREATE) && (name != NULL) &&
+ filename_is_volatile(name, namelen, NULL))
+ op_data->op_bias |= MDS_CREATE_VOLATILE;
op_data->op_opc = opc;
op_data->op_mds = 0;
op_data->op_data = data;
* with d_instantiate().
*/
static int ll_create_it(struct inode *dir, struct dentry *dentry, int mode,
- struct lookup_intent *it)
+ struct lookup_intent *it)
{
- struct inode *inode;
- int rc = 0;
- ENTRY;
+ struct inode *inode;
+ int rc = 0;
+ ENTRY;
- CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
- dentry->d_name.len, dentry->d_name.name, dir->i_ino,
- dir->i_generation, dir, LL_IT2STR(it));
+ CDEBUG(D_VFSTRACE, "VFS Op:name=%.*s,dir=%lu/%u(%p),intent=%s\n",
+ dentry->d_name.len, dentry->d_name.name, dir->i_ino,
+ dir->i_generation, dir, LL_IT2STR(it));
- rc = it_open_error(DISP_OPEN_CREATE, it);
- if (rc)
- RETURN(rc);
+ rc = it_open_error(DISP_OPEN_CREATE, it);
+ if (rc)
+ RETURN(rc);
- inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
- NULL, 0, mode, 0, it);
- if (IS_ERR(inode))
- RETURN(PTR_ERR(inode));
+ inode = ll_create_node(dir, dentry->d_name.name, dentry->d_name.len,
+ NULL, 0, mode, 0, it);
+ if (IS_ERR(inode))
+ RETURN(PTR_ERR(inode));
- d_instantiate(dentry, inode);
- RETURN(0);
+ if (filename_is_volatile(dentry->d_name.name, dentry->d_name.len, NULL))
+ ll_i2info(inode)->lli_volatile = true;
+
+ d_instantiate(dentry, inode);
+ RETURN(0);
}
static void ll_update_times(struct ptlrpc_request *request,
static int __init init_lustre_lite(void)
{
- int i, rc, seed[2];
- struct timeval tv;
- lnet_process_id_t lnet_id;
-
- /* print an address of _any_ initialized kernel symbol from this
- * module, to allow debugging with gdb that doesn't support data
- * symbols from modules.*/
- CDEBUG(D_INFO, "Lustre client module (%p).\n",
- &lustre_super_operations);
+ int i, rc, seed[2];
+ struct timeval tv;
+ lnet_process_id_t lnet_id;
+
+ CLASSERT(sizeof(LUSTRE_VOLATILE_HDR) == LUSTRE_VOLATILE_HDR_LEN + 1);
+
+ /* print an address of _any_ initialized kernel symbol from this
+ * module, to allow debugging with gdb that doesn't support data
+ * symbols from modules.*/
+ CDEBUG(D_INFO, "Lustre client module (%p).\n",
+ &lustre_super_operations);
rc = ll_init_inodecache();
if (rc)
const void *data, int datalen, __u32 mode,
__u32 uid, __u32 gid, cfs_cap_t cap_effective, __u64 rdev)
{
- struct mdt_rec_create *rec;
- char *tmp;
-
- CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_create));
- rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
-
-
- rec->cr_opcode = REINT_CREATE;
- rec->cr_fsuid = uid;
- rec->cr_fsgid = gid;
- rec->cr_cap = cap_effective;
- rec->cr_fid1 = op_data->op_fid1;
- rec->cr_fid2 = op_data->op_fid2;
- rec->cr_mode = mode;
- rec->cr_rdev = rdev;
- rec->cr_time = op_data->op_mod_time;
- rec->cr_suppgid1 = op_data->op_suppgids[0];
- rec->cr_suppgid2 = op_data->op_suppgids[1];
- set_mrc_cr_flags(rec, op_data->op_flags & MF_SOM_LOCAL_FLAGS);
- rec->cr_bias = op_data->op_bias;
- rec->cr_umask = cfs_curproc_umask();
-
- mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1);
-
- tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
- LOGL0(op_data->op_name, op_data->op_namelen, tmp);
-
- if (data) {
- tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
- memcpy(tmp, data, datalen);
- }
+ struct mdt_rec_create *rec;
+ char *tmp;
+ __u64 flags;
+
+ CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_create));
+ rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
+
+
+ rec->cr_opcode = REINT_CREATE;
+ rec->cr_fsuid = uid;
+ rec->cr_fsgid = gid;
+ rec->cr_cap = cap_effective;
+ rec->cr_fid1 = op_data->op_fid1;
+ rec->cr_fid2 = op_data->op_fid2;
+ rec->cr_mode = mode;
+ rec->cr_rdev = rdev;
+ rec->cr_time = op_data->op_mod_time;
+ rec->cr_suppgid1 = op_data->op_suppgids[0];
+ rec->cr_suppgid2 = op_data->op_suppgids[1];
+ flags = op_data->op_flags & MF_SOM_LOCAL_FLAGS;
+ if (op_data->op_bias & MDS_CREATE_VOLATILE)
+ flags |= MDS_OPEN_VOLATILE;
+ set_mrc_cr_flags(rec, flags);
+ rec->cr_bias = op_data->op_bias;
+ rec->cr_umask = cfs_curproc_umask();
+
+ mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1);
+
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
+ LOGL0(op_data->op_name, op_data->op_namelen, tmp);
+
+ if (data) {
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
+ memcpy(tmp, data, datalen);
+ }
}
static __u64 mds_pack_open_flags(__u32 flags, __u32 mode)
/* packing of MDS records */
void mdc_open_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
- __u32 mode, __u64 rdev, __u32 flags, const void *lmm,
- int lmmlen)
+ __u32 mode, __u64 rdev, __u32 flags, const void *lmm,
+ int lmmlen)
{
- struct mdt_rec_create *rec;
- char *tmp;
- __u64 cr_flags;
-
- CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_create));
- rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
-
- /* XXX do something about time, uid, gid */
- rec->cr_opcode = REINT_OPEN;
- rec->cr_fsuid = cfs_curproc_fsuid();
- rec->cr_fsgid = cfs_curproc_fsgid();
- rec->cr_cap = cfs_curproc_cap_pack();
- if (op_data != NULL) {
- rec->cr_fid1 = op_data->op_fid1;
- rec->cr_fid2 = op_data->op_fid2;
- }
- rec->cr_mode = mode;
- cr_flags = mds_pack_open_flags(flags, mode);
- rec->cr_rdev = rdev;
- rec->cr_time = op_data->op_mod_time;
- rec->cr_suppgid1 = op_data->op_suppgids[0];
- rec->cr_suppgid2 = op_data->op_suppgids[1];
- rec->cr_bias = op_data->op_bias;
- rec->cr_umask = cfs_curproc_umask();
-
- mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1);
- /* the next buffer is child capa, which is used for replay,
- * will be packed from the data in reply message. */
-
- if (op_data->op_name) {
- tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
- LOGL0(op_data->op_name, op_data->op_namelen, tmp);
- }
-
- if (lmm) {
- cr_flags |= MDS_OPEN_HAS_EA;
+ struct mdt_rec_create *rec;
+ char *tmp;
+ __u64 cr_flags;
+
+ CLASSERT(sizeof(struct mdt_rec_reint) == sizeof(struct mdt_rec_create));
+ rec = req_capsule_client_get(&req->rq_pill, &RMF_REC_REINT);
+
+ /* XXX do something about time, uid, gid */
+ rec->cr_opcode = REINT_OPEN;
+ rec->cr_fsuid = cfs_curproc_fsuid();
+ rec->cr_fsgid = cfs_curproc_fsgid();
+ rec->cr_cap = cfs_curproc_cap_pack();
+ if (op_data != NULL) {
+ rec->cr_fid1 = op_data->op_fid1;
+ rec->cr_fid2 = op_data->op_fid2;
+ }
+ rec->cr_mode = mode;
+ cr_flags = mds_pack_open_flags(flags, mode);
+ rec->cr_rdev = rdev;
+ rec->cr_time = op_data->op_mod_time;
+ rec->cr_suppgid1 = op_data->op_suppgids[0];
+ rec->cr_suppgid2 = op_data->op_suppgids[1];
+ rec->cr_bias = op_data->op_bias;
+ rec->cr_umask = cfs_curproc_umask();
+
+ mdc_pack_capa(req, &RMF_CAPA1, op_data->op_capa1);
+ /* the next buffer is child capa, which is used for replay,
+ * will be packed from the data in reply message. */
+
+ if (op_data->op_name) {
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_NAME);
+ LOGL0(op_data->op_name, op_data->op_namelen, tmp);
+ if (op_data->op_bias & MDS_CREATE_VOLATILE)
+ cr_flags |= MDS_OPEN_VOLATILE;
+ }
+
+ if (lmm) {
+ cr_flags |= MDS_OPEN_HAS_EA;
#ifndef __KERNEL__
- /*XXX a hack for liblustre to set EA (LL_IOC_LOV_SETSTRIPE) */
- rec->cr_fid2 = op_data->op_fid2;
+ /*XXX a hack for liblustre to set EA (LL_IOC_LOV_SETSTRIPE) */
+ rec->cr_fid2 = op_data->op_fid2;
#endif
- tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
- memcpy (tmp, lmm, lmmlen);
- }
- set_mrc_cr_flags(rec, cr_flags);
+ tmp = req_capsule_client_get(&req->rq_pill, &RMF_EADATA);
+ memcpy(tmp, lmm, lmmlen);
+ }
+ set_mrc_cr_flags(rec, cr_flags);
}
static inline __u64 attr_pack(unsigned int ia_valid) {
}
int mdd_declare_finish_unlink(const struct lu_env *env,
- struct mdd_object *obj,
- struct md_attr *ma,
- struct thandle *handle)
+ struct mdd_object *obj,
+ struct md_attr *ma,
+ struct thandle *handle)
{
- int rc;
+ int rc;
- rc = orph_declare_index_insert(env, obj, handle);
- if (rc)
- return rc;
+ rc = orph_declare_index_insert(env, obj, mdd_object_type(obj), handle);
+ if (rc)
+ return rc;
return mdo_declare_destroy(env, obj, handle);
}
}
rc = mdd_declare_object_initialize(env, c, attr, handle);
- if (rc)
- GOTO(out, rc);
+ if (rc)
+ GOTO(out, rc);
- rc = mdo_declare_index_insert(env, p, mdo2fid(c),
- name->ln_name, handle);
- if (rc)
- GOTO(out, rc);
+ if (spec->sp_cr_flags & MDS_OPEN_VOLATILE)
+ rc = orph_declare_index_insert(env, c, attr->la_mode, handle);
+ else
+ rc = mdo_declare_index_insert(env, p, mdo2fid(c),
+ name->ln_name, handle);
+ if (rc)
+ GOTO(out, rc);
/* replay case, create LOV EA from client data */
if (spec->no_create || (spec->sp_cr_flags & MDS_OPEN_HAS_EA)) {
GOTO(out, rc);
}
- rc = mdo_declare_attr_set(env, p, attr, handle);
- if (rc)
- return rc;
+ if (!(spec->sp_cr_flags & MDS_OPEN_VOLATILE)) {
+ rc = mdo_declare_attr_set(env, p, attr, handle);
+ if (rc)
+ return rc;
+ }
rc = mdd_declare_changelog_store(env, mdd, name, handle);
if (rc)
const struct lu_name *lname, struct md_object *child,
struct md_op_spec *spec, struct md_attr* ma)
{
- struct mdd_thread_info *info = mdd_env_info(env);
- struct lu_attr *la = &info->mti_la_for_fix;
- struct mdd_object *mdd_pobj = md2mdd_obj(pobj);
- struct mdd_object *son = md2mdd_obj(child);
- struct mdd_device *mdd = mdo2mdd(pobj);
- struct lu_attr *attr = &ma->ma_attr;
- struct thandle *handle;
- struct lu_attr *pattr = &info->mti_pattr;
- struct dynlock_handle *dlh;
- const char *name = lname->ln_name;
- int rc, created = 0, initialized = 0, inserted = 0;
- int got_def_acl = 0;
- ENTRY;
+ struct mdd_thread_info *info = mdd_env_info(env);
+ struct lu_attr *la = &info->mti_la_for_fix;
+ struct mdd_object *mdd_pobj = md2mdd_obj(pobj);
+ struct mdd_object *son = md2mdd_obj(child);
+ struct mdd_device *mdd = mdo2mdd(pobj);
+ struct lu_attr *attr = &ma->ma_attr;
+ struct thandle *handle;
+ struct lu_attr *pattr = &info->mti_pattr;
+ struct dynlock_handle *dlh;
+ const char *name = lname->ln_name;
+ int rc, created = 0, initialized = 0, inserted = 0;
+ int got_def_acl = 0;
+ ENTRY;
/*
* Two operations have to be performed:
if (rc)
GOTO(out_stop, rc);
- dlh = mdd_pdo_write_lock(env, mdd_pobj, name, MOR_TGT_PARENT);
- if (dlh == NULL)
- GOTO(out_trans, rc = -ENOMEM);
+ dlh = mdd_pdo_write_lock(env, mdd_pobj, name, MOR_TGT_PARENT);
+ if (dlh == NULL)
+ GOTO(out_trans, rc = -ENOMEM);
- mdd_write_lock(env, son, MOR_TGT_CHILD);
- rc = mdd_object_create_internal(env, mdd_pobj, son, attr, handle, spec);
- if (rc) {
- mdd_write_unlock(env, son);
- GOTO(cleanup, rc);
- }
+ mdd_write_lock(env, son, MOR_TGT_CHILD);
+ rc = mdd_object_create_internal(env, NULL, son, attr, handle, spec);
+ if (rc) {
+ mdd_write_unlock(env, son);
+ GOTO(cleanup, rc);
+ }
- created = 1;
+ created = 1;
#ifdef CONFIG_FS_POSIX_ACL
- if (got_def_acl) {
+ if (got_def_acl) {
struct lu_buf *acl_buf;
acl_buf = mdd_buf_get(env, info->mti_xattr_buf, got_def_acl);
mdd_write_unlock(env, son);
GOTO(cleanup, rc);
}
- }
+ }
#endif
- rc = mdd_object_initialize(env, mdo2fid(mdd_pobj), lname,
+ rc = mdd_object_initialize(env, mdo2fid(mdd_pobj), lname,
son, attr, handle, spec);
/*
* MDT calls this xattr_set(LOV) in a different transaction.
* probably this way we code can be made better.
*/
- if (rc == 0 &&
- (spec->no_create || (spec->sp_cr_flags & MDS_OPEN_HAS_EA))) {
+ if (rc == 0 && (spec->no_create ||
+ (spec->sp_cr_flags & MDS_OPEN_HAS_EA))) {
const struct lu_buf *buf;
buf = mdd_buf_get_const(env, spec->u.sp_ea.eadata,
rc = mdo_xattr_set(env, son, buf, XATTR_NAME_LOV, 0, handle,
BYPASS_CAPA);
}
- mdd_write_unlock(env, son);
- if (rc)
- /*
- * Object has no links, so it will be destroyed when last
- * reference is released. (XXX not now.)
- */
- GOTO(cleanup, rc);
- initialized = 1;
+ if (rc == 0 && spec->sp_cr_flags & MDS_OPEN_VOLATILE)
+ rc = __mdd_orphan_add(env, son, handle);
- rc = __mdd_index_insert(env, mdd_pobj, mdo2fid(son),
- name, S_ISDIR(attr->la_mode), handle,
- mdd_object_capa(env, mdd_pobj));
- if (rc)
- GOTO(cleanup, rc);
+ mdd_write_unlock(env, son);
- inserted = 1;
+ if (rc != 0)
+ /*
+ * Object has no links, so it will be destroyed when last
+ * reference is released. (XXX not now.)
+ */
+ GOTO(cleanup, rc);
+
+ initialized = 1;
+
+ if (!(spec->sp_cr_flags & MDS_OPEN_VOLATILE))
+ rc = __mdd_index_insert(env, mdd_pobj, mdo2fid(son),
+ name, S_ISDIR(attr->la_mode), handle,
+ mdd_object_capa(env, mdd_pobj));
+
+ if (rc != 0)
+ GOTO(cleanup, rc);
+
+ inserted = 1;
if (S_ISLNK(attr->la_mode)) {
struct lu_ucred *uc = lu_ucred_assert(env);
GOTO(cleanup, rc = -EFAULT);
}
+ /* volatile file creation does not update parent directory times */
+ if (spec->sp_cr_flags & MDS_OPEN_VOLATILE)
+ GOTO(cleanup, rc = 0);
+
+ /* update parent directory mtime/ctime */
*la = *attr;
- la->la_valid = LA_CTIME | LA_MTIME;
+ la->la_valid = LA_CTIME | LA_MTIME;
rc = mdd_attr_check_set_internal(env, mdd_pobj, la, handle, 0);
- if (rc)
- GOTO(cleanup, rc);
+ if (rc)
+ GOTO(cleanup, rc);
EXIT;
cleanup:
int rc2;
if (inserted != 0) {
- rc2 = __mdd_index_delete(env, mdd_pobj, name,
- S_ISDIR(attr->la_mode),
- handle, BYPASS_CAPA);
+ if (spec->sp_cr_flags & MDS_OPEN_VOLATILE)
+ rc2 = __mdd_orphan_del(env, son, handle);
+ else
+ rc2 = __mdd_index_delete(env, mdd_pobj, name,
+ S_ISDIR(attr->la_mode),
+ handle, BYPASS_CAPA);
if (rc2 != 0)
goto out_stop;
}
int orph_index_init(const struct lu_env *env, struct mdd_device *mdd);
void orph_index_fini(const struct lu_env *env, struct mdd_device *mdd);
int orph_declare_index_insert(const struct lu_env *, struct mdd_object *,
- struct thandle *);
+ cfs_umode_t mode, struct thandle *);
int orph_declare_index_delete(const struct lu_env *, struct mdd_object *,
struct thandle *);
int orph_declare_index_insert(const struct lu_env *env,
- struct mdd_object *obj,
- struct thandle *th)
+ struct mdd_object *obj,
+ cfs_umode_t mode, struct thandle *th)
{
- struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
- struct dt_key *key;
- int rc;
+ struct mdd_device *mdd = mdo2mdd(&obj->mod_obj);
+ struct dt_key *key;
+ int rc;
key = orph_key_fill(env, mdo2fid(obj), ORPH_OP_UNLINK);
rc = dt_declare_insert(env, mdd->mdd_orphans, NULL, key, th);
- if (rc)
- return rc;
+ if (rc)
+ return rc;
- rc = mdo_declare_ref_add(env, obj, th);
- if (rc)
- return rc;
+ rc = mdo_declare_ref_add(env, obj, th);
+ if (rc)
+ return rc;
- if (!S_ISDIR(mdd_object_type(obj)))
- return 0;
+ if (!S_ISDIR(mode))
+ return 0;
- rc = mdo_declare_ref_add(env, obj, th);
- if (rc)
- return rc;
+ rc = mdo_declare_ref_add(env, obj, th);
+ if (rc)
+ return rc;
- rc = dt_declare_ref_add(env, mdd->mdd_orphans, th);
- if (rc)
- return rc;
+ rc = dt_declare_ref_add(env, mdd->mdd_orphans, th);
+ if (rc)
+ return rc;
- rc = mdo_declare_index_delete(env, obj, dotdot, th);
- if (rc)
- return rc;
+ rc = mdo_declare_index_delete(env, obj, dotdot, th);
+ if (rc)
+ return rc;
- rc = mdo_declare_index_insert(env, obj, NULL, dotdot, th);
+ rc = mdo_declare_index_insert(env, obj, NULL, dotdot, th);
- return rc;
+ return rc;
}
static int orph_index_insert(const struct lu_env *env,
LASSERT(mdd_write_locked(env, obj) != 0);
LASSERT(!(obj->mod_flags & ORPHAN_OBJ));
- LASSERT(obj->mod_count > 0);
mdd_orphan_write_lock(env, mdd);
int raw_name2idx(int hashtype, int count, const char *name, int namelen)
{
- unsigned int c = 0;
+ unsigned int c = 0;
+ int idx;
- LASSERT(namelen > 0);
- if (count <= 1)
- return 0;
+ LASSERT(namelen > 0);
- switch (hashtype) {
- case MEA_MAGIC_LAST_CHAR:
- c = mea_last_char_hash(count, (char *)name, namelen);
- break;
- case MEA_MAGIC_ALL_CHARS:
- c = mea_all_chars_hash(count, (char *)name, namelen);
- break;
- case MEA_MAGIC_HASH_SEGMENT:
- CERROR("Unsupported hash type MEA_MAGIC_HASH_SEGMENT\n");
- break;
- default:
- CERROR("Unknown hash type 0x%x\n", hashtype);
- }
+ if (filename_is_volatile(name, namelen, &idx)) {
+ if ((idx >= 0) && (idx < count))
+ return idx;
+ goto hashchoice;
+ }
- LASSERT(c < count);
- return c;
+ if (count <= 1)
+ return 0;
+
+hashchoice:
+ switch (hashtype) {
+ case MEA_MAGIC_LAST_CHAR:
+ c = mea_last_char_hash(count, (char *)name, namelen);
+ break;
+ case MEA_MAGIC_ALL_CHARS:
+ c = mea_all_chars_hash(count, (char *)name, namelen);
+ break;
+ case MEA_MAGIC_HASH_SEGMENT:
+ CERROR("Unsupported hash type MEA_MAGIC_HASH_SEGMENT\n");
+ break;
+ default:
+ CERROR("Unknown hash type 0x%x\n", hashtype);
+ }
+
+ LASSERT(c < count);
+ return c;
}
EXPORT_SYMBOL(raw_name2idx);
clear_nlink(inode);
spin_unlock(&obj->oo_guard);
inode->i_sb->s_op->dirty_inode(inode);
- } else {
- LASSERT(osd_inode_unlinked(inode));
}
OSD_EXEC_OP(th, destroy);
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2012, Intel Corporation.
+ * Copyright (c) 2011, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
{
/* Wire protocol assertions generated by 'wirecheck'
* (make -C lustre/utils newwiretest)
- * running on Linux mercury 2.6.32-279.5.1.el6_lustre.x86_64 #1 SMP Tue Aug 21 00:00:41 PDT 2
- * with gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) */
+ * running on Linux centos6-bis 2.6.32-279.2.1.el6-head #0 SMP Thu Aug 9 23:25:09 CEST 2012 x
+ * with gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) */
/* Constants... */
(long long)MDS_OPEN_NORESTORE);
LASSERTF(MDS_OPEN_NEWSTRIPE == 00000000000200000000000ULL, "found 0%.22lloULL\n",
(long long)MDS_OPEN_NEWSTRIPE);
+ LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n",
+ (long long)MDS_OPEN_VOLATILE);
LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n",
LUSTRE_SYNC_FL);
LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n",
#include <semaphore.h>
#include <time.h>
+#include <lustre/lustre_idl.h>
#include <lustre/lustreapi.h>
#define T1 "write data before unlink\n"
char *buf, *buf_align;
int bufsize = 0;
sem_t sem;
-#define ALIGN 65535
+#define ALIGN_LEN 65535
char usage[] =
"Usage: %s filename command-sequence\n"
" d mkdir\n"
" D open(O_DIRECTORY)\n"
" f statfs\n"
+" F print FID\n"
" G gid get grouplock\n"
" g gid put grouplock\n"
" L link\n"
" u unlink\n"
" U munmap\n"
" v verbose\n"
+" V open a volatile file\n"
" w[num] write optional length\n"
" W write entire mmap-ed region\n"
" y fsync\n"
int main(int argc, char **argv)
{
- char *fname, *commands;
- const char *newfile;
- struct stat st;
- struct statfs stfs;
- size_t mmap_len = 0, i;
- unsigned char *mmap_ptr = NULL, junk = 0;
- int rc, len, fd = -1;
- int flags;
- int save_errno;
- int verbose = 0;
- int gid = 0;
- struct timespec ts;
+ char *fname, *commands;
+ const char *newfile;
+ struct stat st;
+ struct statfs stfs;
+ size_t mmap_len = 0, i;
+ unsigned char *mmap_ptr = NULL, junk = 0;
+ int rc, len, fd = -1;
+ int flags;
+ int save_errno;
+ int verbose = 0;
+ int gid = 0;
+ lustre_fid fid;
+ struct timespec ts;
if (argc < 3) {
fprintf(stderr, usage, argv[0]);
exit(save_errno);
}
break;
+ case 'F':
+ if (fd == -1)
+ rc = llapi_path2fid(fname, &fid);
+ else
+ rc = llapi_fd2fid(fd, &fid);
+ if (rc != 0)
+ fprintf(stderr,
+ "llapi_path/fd2fid() on %d, rc=%d\n",
+ fd, rc);
+ else
+ printf(DFID"\n", PFID(&fid));
+ break;
case 'G':
gid = atoi(commands+1);
if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
exit(save_errno);
}
break;
- case 'r':
- len = atoi(commands+1);
- if (len <= 0)
- len = 1;
- if (bufsize < len) {
- buf = realloc(buf, len + ALIGN);
- if (buf == NULL) {
- save_errno = errno;
- perror("allocating buf for read\n");
- exit(save_errno);
- }
- bufsize = len;
- buf_align = (char *)((long)(buf + ALIGN) &
- ~ALIGN);
- }
- while (len > 0) {
- rc = read(fd, buf_align, len);
- if (rc == -1) {
- save_errno = errno;
- perror("read");
- exit(save_errno);
- }
+ case 'r':
+ len = atoi(commands+1);
+ if (len <= 0)
+ len = 1;
+ if (bufsize < len) {
+ buf = realloc(buf, len + ALIGN_LEN);
+ if (buf == NULL) {
+ save_errno = errno;
+ perror("allocating buf for read\n");
+ exit(save_errno);
+ }
+ bufsize = len;
+ buf_align = (char *)((long)(buf + ALIGN_LEN) &
+ ~ALIGN_LEN);
+ }
+ while (len > 0) {
+ rc = read(fd, buf_align, len);
+ if (rc == -1) {
+ save_errno = errno;
+ perror("read");
+ exit(save_errno);
+ }
if (rc < len) {
fprintf(stderr, "short read: %u/%u\n",
rc, len);
if (rc == 0)
exit(ENODATA);
}
- len -= rc;
- if (verbose >= 2)
- printf("%.*s\n", rc, buf_align);
- }
- break;
+ len -= rc;
+ if (verbose >= 2)
+ printf("%.*s\n", rc, buf_align);
+ }
+ break;
case 'R':
for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
junk += mmap_ptr[i];
case 'v':
verbose++;
break;
- case 'w':
- len = atoi(commands+1);
- if (len <= 0)
- len = 1;
- if (bufsize < len) {
- buf = realloc(buf, len + ALIGN);
- if (buf == NULL) {
- save_errno = errno;
- perror("allocating buf for write\n");
- exit(save_errno);
- }
- bufsize = len;
- buf_align = (char *)((long)(buf + ALIGN) &
- ~ALIGN);
- strncpy(buf_align, msg, bufsize);
- }
- while (len > 0) {
- rc = write(fd, buf_align, len);
- if (rc == -1) {
- save_errno = errno;
- perror("write");
- exit(save_errno);
- }
- if (rc < len)
- fprintf(stderr, "short write: %u/%u\n",
- rc, len);
- len -= rc;
- }
- break;
+ case 'V':
+ len = get_flags(commands + 1, &flags);
+ commands += len;
+ fd = llapi_create_volatile(fname, flags);
+ if (fd < 0) {
+ perror("llapi_create_volatile");
+ exit(fd);
+ }
+ break;
+ case 'w':
+ len = atoi(commands+1);
+ if (len <= 0)
+ len = 1;
+ if (bufsize < len) {
+ buf = realloc(buf, len + ALIGN_LEN);
+ if (buf == NULL) {
+ save_errno = errno;
+ perror("allocating buf for write\n");
+ exit(save_errno);
+ }
+ bufsize = len;
+ buf_align = (char *)((long)(buf + ALIGN_LEN) &
+ ~ALIGN_LEN);
+ strncpy(buf_align, msg, bufsize);
+ }
+ while (len > 0) {
+ rc = write(fd, buf_align, len);
+ if (rc == -1) {
+ save_errno = errno;
+ perror("write");
+ exit(save_errno);
+ }
+ if (rc < len)
+ fprintf(stderr, "short write: %u/%u\n",
+ rc, len);
+ len -= rc;
+ }
+ break;
case 'W':
for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
mmap_ptr[i] += junk++;
}
run_test 183 "No crash or request leak in case of strange dispositions ========"
+test_185() { # LU-2441
+ mkdir -p $DIR/$tdir || error "creating dir $DIR/$tdir"
+ touch $DIR/$tdir/spoo
+ local mtime1=$(stat -c "%Y" $DIR/$tdir)
+ local fid=$($MULTIOP $DIR/$tdir VFw4096c) ||
+ error "cannot create/write a volatile file"
+ $CHECKSTAT -t file $MOUNT/.lustre/fid/$fid 2>/dev/null &&
+ error "FID is still valid after close"
+
+ multiop_bg_pause $DIR/$tdir vVw4096_c
+ local multi_pid=$!
+
+ local OLD_IFS=$IFS
+ IFS=":"
+ local fidv=($fid)
+ IFS=$OLD_IFS
+ # assume that the next FID for this client is sequential, since stdout
+ # is unfortunately eaten by multiop_bg_pause
+ local n=$((${fidv[1]} + 1))
+ local next_fid="${fidv[0]}:$(printf "0x%x" $n):${fidv[2]}"
+ $CHECKSTAT -t file $MOUNT/.lustre/fid/$next_fid ||
+ error "FID is missing before close"
+ kill -USR1 $multi_pid
+ # 1 second delay, so if mtime change we will see it
+ sleep 1
+ local mtime2=$(stat -c "%Y" $DIR/$tdir)
+ [[ $mtime1 == $mtime2 ]] || error "mtime has changed"
+}
+run_test 185 "Volatile file support"
+
# OST pools tests
check_file_in_pool()
{
return rc;
}
-static int path2fid_from_lma(const char *path, lustre_fid *fid)
+static int fid_from_lma(const char *path, const int fd, lustre_fid *fid)
+{
+ char buf[512];
+ struct lustre_mdt_attrs *lma;
+ int rc;
+
+ if (path == NULL)
+ rc = fgetxattr(fd, XATTR_NAME_LMA, buf, sizeof(buf));
+ else
+ rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
+ if (rc < 0)
+ return -errno;
+ lma = (struct lustre_mdt_attrs *)buf;
+ fid_le_to_cpu(fid, &lma->lma_self_fid);
+ return 0;
+}
+
+int llapi_fd2fid(const int fd, lustre_fid *fid)
{
- char buf[512];
- struct lustre_mdt_attrs *lma;
- int rc;
+ int rc;
- rc = lgetxattr(path, XATTR_NAME_LMA, buf, sizeof(buf));
- if (rc < 0)
- return -errno;
- lma = (struct lustre_mdt_attrs *)buf;
- fid_le_to_cpu(fid, &lma->lma_self_fid);
- return 0;
+ memset(fid, 0, sizeof(*fid));
+
+ rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0;
+ if (rc == -EINVAL || rc == -ENOTTY)
+ rc = fid_from_lma(NULL, fd, fid);
+
+ return rc;
}
int llapi_path2fid(const char *path, lustre_fid *fid)
{
- int fd, rc;
+ int fd, rc;
- memset(fid, 0, sizeof(*fid));
- fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
- if (fd < 0) {
- if (errno == ELOOP || errno == ENXIO)
- return path2fid_from_lma(path, fid);
- return -errno;
- }
+ memset(fid, 0, sizeof(*fid));
+ fd = open(path, O_RDONLY | O_NONBLOCK | O_NOFOLLOW);
+ if (fd < 0) {
+ if (errno == ELOOP || errno == ENXIO)
+ return fid_from_lma(path, -1, fid);
+ return -errno;
+ }
- rc = ioctl(fd, LL_IOC_PATH2FID, fid) < 0 ? -errno : 0;
- if (rc == -EINVAL || rc == -ENOTTY)
- rc = path2fid_from_lma(path, fid);
+ rc = llapi_fd2fid(fd, fid);
+ if (rc == -EINVAL || rc == -ENOTTY)
+ rc = fid_from_lma(path, -1, fid);
- close(fd);
- return rc;
+ close(fd);
+ return rc;
}
/****** HSM Copytool API ********/
return rc;
}
+
+/*
+ * Create a volatile file and open it for write:
+ * - file is created as a standard file in the directory
+ * - file does not appears in directory and directory mtime does not change
+ * - file is removed at close
+ * - file modes are rw-------, if user wants another one it must use fchmod()
+ * \param directory Directory where the file is created
+ * \param idx MDT index on which the file is created
+ * \param flags Std open flags
+ *
+ * \retval 0 on success.
+ * \retval -errno on error.
+ */
+int llapi_create_volatile_idx(char *directory, int idx, int mode)
+{
+ char file_path[PATH_MAX];
+ char filename[PATH_MAX];
+ int fd;
+ int random;
+ int rc;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd < 0) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "Cannot open /dev/urandom\n");
+ return -errno;
+ }
+ rc = read(fd, &random, sizeof(random));
+ close(fd);
+ if (rc < sizeof(random)) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "Cannot read %d bytes from /dev/urandom\n",
+ sizeof(random));
+ return -errno;
+ }
+ if (idx == -1)
+ sprintf(filename, LUSTRE_VOLATILE_HDR"::%.4X", random);
+ else
+ sprintf(filename, LUSTRE_VOLATILE_IDX"%.4X", 0, random);
+
+ sprintf(file_path, "%s/%s", directory, filename);
+
+ fd = open(file_path, O_RDWR|O_CREAT|mode, S_IRUSR|S_IWUSR);
+ if (fd < 0) {
+ llapi_error(LLAPI_MSG_ERROR, errno,
+ "Cannot create volatile file %s in %s\n",
+ filename + LUSTRE_VOLATILE_HDR_LEN,
+ directory);
+ return -errno;
+ }
+ return fd;
+}
+
+
CHECK_VALUE_O(MDS_OPEN_HAS_OBJS);
CHECK_VALUE_64O(MDS_OPEN_NORESTORE);
CHECK_VALUE_64O(MDS_OPEN_NEWSTRIPE);
+ CHECK_VALUE_64O(MDS_OPEN_VOLATILE);
/* these should be identical to their EXT3_*_FL counterparts, and
* are redefined only to avoid dragging in ext3_fs.h */
{
/* Wire protocol assertions generated by 'wirecheck'
* (make -C lustre/utils newwiretest)
- * running on Linux mercury 2.6.32-279.5.1.el6_lustre.x86_64 #1 SMP Tue Aug 21 00:00:41 PDT 2
- * with gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) */
+ * running on Linux centos6-bis 2.6.32-279.2.1.el6-head #0 SMP Thu Aug 9 23:25:09 CEST 2012 x
+ * with gcc version 4.4.6 20110731 (Red Hat 4.4.6-3) (GCC) */
/* Constants... */
(long long)MDS_OPEN_NORESTORE);
LASSERTF(MDS_OPEN_NEWSTRIPE == 00000000000200000000000ULL, "found 0%.22lloULL\n",
(long long)MDS_OPEN_NEWSTRIPE);
+ LASSERTF(MDS_OPEN_VOLATILE == 00000000000400000000000ULL, "found 0%.22lloULL\n",
+ (long long)MDS_OPEN_VOLATILE);
LASSERTF(LUSTRE_SYNC_FL == 0x00000008, "found 0x%.8x\n",
LUSTRE_SYNC_FL);
LASSERTF(LUSTRE_IMMUTABLE_FL == 0x00000010, "found 0x%.8x\n",