LUSTRE_TOPDIR_FL = 0x00020000, /* Top of directory hierarchies*/
LUSTRE_DIRECTIO_FL = 0x00100000, /* Use direct i/o */
LUSTRE_INLINE_DATA_FL = 0x10000000, /* Inode has inline data. */
+ LUSTRE_PROJINHERIT_FL = 0x20000000, /* Create with parents projid */
/* These flags will not be identical to any EXT4_*_FL counterparts,
* and only reserved for lustre purpose. Note: these flags might
LUSTRE_LMA_FL_MASKS = LUSTRE_ORPHAN_FL,
};
+#ifndef FS_XFLAG_PROJINHERIT
+#define FS_XFLAG_PROJINHERIT 0x00000200 /* create with parents projid */
+#endif
+
#ifdef __KERNEL__
/* Convert wire LUSTRE_*_FL to corresponding client local VFS S_* values
* for the client inode i_flags. The LUSTRE_*_FL are the Lustre wire
#if defined(S_DIRSYNC)
((flags & LUSTRE_DIRSYNC_FL) ? S_DIRSYNC : 0) |
#endif
- ((flags & LUSTRE_IMMUTABLE_FL) ? S_IMMUTABLE : 0));
+ ((flags & LUSTRE_IMMUTABLE_FL) ? S_IMMUTABLE : 0) |
+ ((flags & LUSTRE_PROJINHERIT_FL) ? FS_XFLAG_PROJINHERIT : 0));
}
static inline int ll_inode_to_ext_flags(int iflags)
#if defined(S_DIRSYNC)
((iflags & S_DIRSYNC) ? LUSTRE_DIRSYNC_FL : 0) |
#endif
- ((iflags & S_IMMUTABLE) ? LUSTRE_IMMUTABLE_FL : 0));
+ ((iflags & S_IMMUTABLE) ? LUSTRE_IMMUTABLE_FL : 0) |
+ ((iflags & FS_XFLAG_PROJINHERIT) ? LUSTRE_PROJINHERIT_FL : 0));
}
#endif
if (rc != 0)
RETURN(rc);
+ /*
+ * If we are using project inheritance, we only allow hard link
+ * creation in our tree when the project IDs are the same;
+ * otherwise the tree quota mechanism could be circumvented.
+ */
+ if ((tattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
+ (tattr->la_projid != cattr->la_projid))
+ RETURN(-EXDEV);
+
handle = mdd_trans_create(env, mdd);
if (IS_ERR(handle))
GOTO(out_pending, rc = PTR_ERR(handle));
}
}
+ /* Inherit project ID from parent directory */
+ if (pattr->la_flags & LUSTRE_PROJINHERIT_FL) {
+ cattr->la_projid = pattr->la_projid;
+ if (S_ISDIR(cattr->la_mode)) {
+ cattr->la_flags |= LUSTRE_PROJINHERIT_FL;
+ cattr->la_valid |= LA_FLAGS;
+ }
+ cattr->la_valid |= LA_PROJID;
+ }
+
rc = mdd_name_check(m, lname);
if (rc < 0)
RETURN(rc);
* before mdd_rename and enable MDS_PERM_BYPASS. */
LASSERT(sobj);
+ /*
+ * If we are using project inheritance, we only allow renames
+ * into our tree when the project IDs are the same; otherwise
+ * tree quota mechanism would be circumvented.
+ */
+ if (((tpattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
+ tpattr->la_projid != cattr->la_projid) ||
+ ((pattr->la_flags & LUSTRE_PROJINHERIT_FL) &&
+ (pattr->la_projid != tpattr->la_projid)))
+ RETURN(-EXDEV);
+
rc = mdd_may_delete(env, src_pobj, pattr, sobj, cattr, NULL, 1, 0);
if (rc)
RETURN(rc);
attr->la_rdev = inode->i_rdev;
attr->la_blksize = 1 << inode->i_blkbits;
attr->la_blkbits = inode->i_blkbits;
+ /*
+ * Ext4 did not transfer inherit flags from raw inode
+ * to inode flags, and ext4 internally test raw inode
+ * @i_flags directly. Instead of patching ext4, we do it here.
+ */
+ if (LDISKFS_I(inode)->i_flags & LUSTRE_PROJINHERIT_FL)
+ attr->la_flags |= LUSTRE_PROJINHERIT_FL;
}
static int osd_attr_get(const struct lu_env *env,
/* always keep S_NOCMTIME */
inode->i_flags = ll_ext_to_inode_flags(attr->la_flags) |
S_NOCMTIME;
+ /*
+ * Ext4 did not transfer inherit flags from
+ * @inode->i_flags to raw inode i_flags when writing
+ * flags, we do it explictly here.
+ */
+ if (attr->la_flags & LUSTRE_PROJINHERIT_FL)
+ LDISKFS_I(inode)->i_flags |= LUSTRE_PROJINHERIT_FL;
}
return 0;
}
}
#ifdef HAVE_PROJECT_QUOTA
- /* Handle project id Transfer here properly */
+ /* Handle project id transfer here properly */
if (attr->la_valid & LA_PROJID && attr->la_projid !=
i_projid_read(inode)) {
rc = __ldiskfs_ioctl_setproject(inode, attr->la_projid);
ldiskfs_set_inode_state(local, LDISKFS_STATE_LUSTRE_NOSCRUB);
unlock_new_inode(local);
+ /* Agent inode should not have project ID*/
+#ifdef HAVE_PROJECT_QUOTA
+ if (LDISKFS_I(pobj->oo_inode)->i_flags & LUSTRE_PROJINHERIT_FL) {
+ rc = __ldiskfs_ioctl_setproject(local, 0);
+ if (rc) {
+ CERROR("%s: quota transfer failed: rc = %d. Is project "
+ "quota enforcement enabled on the ldiskfs "
+ "filesystem?\n", local->i_sb->s_id, rc);
+ RETURN(ERR_PTR(rc));
+ }
+ }
+
+#endif
/* Set special LMA flag for local agent inode */
rc = osd_ea_fid_set(info, local, fid, 0, LMAI_AGENT);
if (rc != 0) {
obdo->o_valid = 0;
obdo_from_la(obdo, la, la->la_valid);
- lustre_set_wire_obdo(NULL, obdo, obdo);
out_unlock:
dt_read_unlock(env, obj);
obdo->o_valid = 0;
obdo_from_la(obdo, attr, attr->la_valid);
- lustre_set_wire_obdo(NULL, obdo, obdo);
if (parent_fid != NULL) {
struct lu_fid *tmp;
obdo->o_valid = 0;
obdo_from_la(obdo, attr, attr->la_valid);
- lustre_set_wire_obdo(NULL, obdo, obdo);
RETURN(0);
}
obdo = &update_env_info(env)->uti_obdo;
obdo->o_valid = 0;
obdo_from_la(obdo, attr, attr->la_valid);
- lustre_set_wire_obdo(NULL, obdo, obdo);
bufs[buf_count] = obdo;
sizes[buf_count] = sizeof(*obdo);
buf_count++;
obdo->o_valid = 0;
obdo_from_la(obdo, attr, attr->la_valid);
- lustre_set_wire_obdo(NULL, obdo, obdo);
return update_records_update_pack(env, fid, OUT_ATTR_SET, ops, op_count,
max_ops_size, params, param_count,
max_param_size, 1,