Whamcloud - gitweb
LU-2441 mdd: Implement volatile file
authorjcl <jacques-charles.lafoucriere@cea.fr>
Mon, 17 Dec 2012 00:55:30 +0000 (01:55 +0100)
committerOleg Drokin <green@whamcloud.com>
Wed, 30 Jan 2013 05:33:55 +0000 (00:33 -0500)
Add a way to create files which are created unlinked, so
they are automatically removed at last close

User interface is:
- llapi_create_volatile_idx()
- llapi_create_volatile()

Signed-off-by: JC Lafoucriere <jacques-charles.lafoucriere@cea.fr>
Change-Id: Ia33a6832d31b83191e4d364da4350cedbe6eef39
Reviewed-on: http://review.whamcloud.com/4836
Tested-by: Hudson
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Johann Lombardi <johann.lombardi@intel.com>
Reviewed-by: Jinshan Xiong <jinshan.xiong@intel.com>
20 files changed:
lustre/include/lustre/lustre_idl.h
lustre/include/lustre/lustre_user.h
lustre/include/lustre/lustreapi.h
lustre/include/obd.h
lustre/llite/llite_internal.h
lustre/llite/llite_lib.c
lustre/llite/namei.c
lustre/llite/super25.c
lustre/mdc/mdc_lib.c
lustre/mdd/mdd_dir.c
lustre/mdd/mdd_internal.h
lustre/mdd/mdd_orphans.c
lustre/obdclass/mea.c
lustre/osd-ldiskfs/osd_handler.c
lustre/ptlrpc/wiretest.c
lustre/tests/multiop.c
lustre/tests/sanity.sh
lustre/utils/liblustreapi.c
lustre/utils/wirecheck.c
lustre/utils/wiretest.c

index 7433243..8dac1cc 100644 (file)
@@ -2129,6 +2129,8 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
 #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)
@@ -2148,16 +2150,17 @@ extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
 #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 */
index 943294d..baa3373 100644 (file)
@@ -466,6 +466,14 @@ enum {
 
 #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;
index 3dc0f6c..b53e7d5 100644 (file)
@@ -200,7 +200,6 @@ extern int llapi_search_ost(char *fsname, char *poolname, char *ostname);
 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);
@@ -216,7 +215,8 @@ extern int llapi_quotachown(char *path, int flag);
 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[]);
@@ -225,12 +225,20 @@ extern int llapi_rgetfacl(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 */
index 3455924..cdf0a5f 100644 (file)
@@ -1746,4 +1746,46 @@ static inline const char *lu_dev_name(const struct lu_device *lu_dev)
         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 */
index 90c5790..2e925f6 100644 (file)
@@ -229,6 +229,11 @@ struct ll_inode_info {
                        /* 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
@@ -252,6 +257,7 @@ struct ll_inode_info {
 #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;
 
index dac77f0..a2c6370 100644 (file)
@@ -934,6 +934,7 @@ void ll_lli_init(struct ll_inode_info *lli)
                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);
 }
@@ -2300,6 +2301,9 @@ struct md_op_data * ll_prep_md_op_data(struct md_op_data *op_data,
        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;
index 6f897e3..5d3f67b 100644 (file)
@@ -833,27 +833,30 @@ static struct inode *ll_create_node(struct inode *dir, const char *name,
  * 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,
index 58ec673..3f6aadf 100644 (file)
@@ -111,15 +111,17 @@ void vvp_global_fini(void);
 
 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)
index 7f7f775..13d055e 100644 (file)
@@ -132,37 +132,41 @@ void mdc_create_pack(struct ptlrpc_request *req, struct md_op_data *op_data,
                      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)
@@ -198,53 +202,55 @@ 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) {
index dcb754d..68e1162 100644 (file)
@@ -1013,15 +1013,15 @@ out_pending:
 }
 
 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);
 }
@@ -1594,13 +1594,16 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd,
         }
 
        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)) {
@@ -1622,9 +1625,11 @@ static int mdd_declare_create(const struct lu_env *env, struct mdd_device *mdd,
                         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)
@@ -1642,19 +1647,19 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                      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:
@@ -1734,21 +1739,21 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
         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);
@@ -1757,10 +1762,10 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                        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);
 
        /*
@@ -1769,8 +1774,8 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
         *      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,
@@ -1778,23 +1783,30 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                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);
@@ -1816,11 +1828,16 @@ static int mdd_create(const struct lu_env *env, struct md_object *pobj,
                         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:
@@ -1828,9 +1845,12 @@ 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;
                }
index bb4f5c4..169d05c 100644 (file)
@@ -361,7 +361,7 @@ int __mdd_orphan_del(const struct lu_env *, struct mdd_object *,
 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 *);
 
index 77944c6..6a741a3 100644 (file)
@@ -155,41 +155,41 @@ static inline void mdd_orphan_ref_del(const struct lu_env *env,
 
 
 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,
@@ -206,7 +206,6 @@ 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);
 
index 1082cbc..2a1ee39 100644 (file)
@@ -69,28 +69,37 @@ static int mea_all_chars_hash(int count, char *name, int namelen)
 
 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);
 
index 0dbfaaa..aa1dcf6 100644 (file)
@@ -2114,8 +2114,6 @@ static int osd_object_destroy(const struct lu_env *env,
                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);
index 1201e46..afa6ae9 100644 (file)
@@ -27,7 +27,7 @@
  * 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/
@@ -54,8 +54,8 @@ void lustre_assert_wire_constants(void)
 {
         /* 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... */
@@ -2043,6 +2043,8 @@ void lustre_assert_wire_constants(void)
                  (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",
index ab360c4..814bd88 100644 (file)
@@ -52,6 +52,7 @@
 #include <semaphore.h>
 #include <time.h>
 
+#include <lustre/lustre_idl.h>
 #include <lustre/lustreapi.h>
 
 #define T1 "write data before unlink\n"
@@ -60,7 +61,7 @@ char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't kno
 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"
@@ -70,6 +71,7 @@ char usage[] =
 "        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"
@@ -88,6 +90,7 @@ char usage[] =
 "        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"
@@ -188,18 +191,19 @@ int get_flags(char *data, int *rflags)
 
 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]);
@@ -268,6 +272,18 @@ int main(int argc, char **argv)
                                 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) {
@@ -357,39 +373,39 @@ int main(int argc, char **argv)
                                 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];
@@ -441,35 +457,44 @@ int main(int argc, char **argv)
                 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++;
index fce0fe1..ffe70d6 100644 (file)
@@ -9266,6 +9266,36 @@ test_183() { # LU-2275
 }
 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()
 {
index ab65f33..4939034 100644 (file)
@@ -3711,38 +3711,54 @@ int llapi_fid2path(const char *device, const char *fidstr, char *buf,
         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 ********/
@@ -4001,3 +4017,58 @@ int llapi_get_data_version(int fd, __u64 *data_version, __u64 flags)
 
         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;
+}
+
+
index 0970513..faba586 100644 (file)
@@ -926,6 +926,7 @@ check_mdt_body(void)
         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 */
index da171e3..8b76073 100644 (file)
@@ -62,8 +62,8 @@ void lustre_assert_wire_constants(void)
 {
         /* 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... */
@@ -2051,6 +2051,8 @@ void lustre_assert_wire_constants(void)
                  (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",