/* llo_* api support */
#include <md_object.h>
+/* dt_acct_features */
+#include <lquota.h>
#ifdef HAVE_LDISKFS_PDO
int ldiskfs_pdo = 1;
return 0;
}
+static int osd_quota_transfer(struct inode *inode, const struct lu_attr *attr)
+{
+ if ((attr->la_valid & LA_UID && attr->la_uid != inode->i_uid) ||
+ (attr->la_valid & LA_GID && attr->la_gid != inode->i_gid)) {
+ struct iattr iattr;
+ int rc;
+
+ iattr.ia_valid = 0;
+ if (attr->la_valid & LA_UID)
+ iattr.ia_valid |= ATTR_UID;
+ if (attr->la_valid & LA_GID)
+ iattr.ia_valid |= ATTR_GID;
+ iattr.ia_uid = attr->la_uid;
+ iattr.ia_gid = attr->la_gid;
+
+ rc = ll_vfs_dq_transfer(inode, &iattr);
+ if (rc) {
+ CERROR("%s: quota transfer failed: rc = %d. Is quota "
+ "enforcement enabled on the ldiskfs filesystem?",
+ inode->i_sb->s_id, rc);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int osd_attr_set(const struct lu_env *env,
struct dt_object *dt,
const struct lu_attr *attr,
OSD_EXEC_OP(handle, attr_set);
inode = obj->oo_inode;
+ if (LDISKFS_HAS_RO_COMPAT_FEATURE(inode->i_sb,
+ LDISKFS_FEATURE_RO_COMPAT_QUOTA)) {
+ rc = osd_quota_transfer(inode, attr);
+ if (rc)
+ return rc;
+ } else {
#ifdef HAVE_QUOTA_SUPPORT
- if ((attr->la_valid & LA_UID && attr->la_uid != inode->i_uid) ||
- (attr->la_valid & LA_GID && attr->la_gid != inode->i_gid)) {
- struct osd_ctxt *save = &osd_oti_get(env)->oti_ctxt;
- struct iattr iattr;
- int rc;
-
- iattr.ia_valid = 0;
- if (attr->la_valid & LA_UID)
- iattr.ia_valid |= ATTR_UID;
- if (attr->la_valid & LA_GID)
- iattr.ia_valid |= ATTR_GID;
- iattr.ia_uid = attr->la_uid;
- iattr.ia_gid = attr->la_gid;
- osd_push_ctxt(env, save);
- rc = ll_vfs_dq_transfer(inode, &iattr) ? -EDQUOT : 0;
- osd_pop_ctxt(save);
- if (rc != 0)
- return rc;
- }
+ if ((attr->la_valid & LA_UID && attr->la_uid != inode->i_uid) ||
+ (attr->la_valid & LA_GID && attr->la_gid != inode->i_gid)) {
+ struct osd_ctxt *save = &osd_oti_get(env)->oti_ctxt;
+ struct iattr iattr;
+ int rc;
+
+ iattr.ia_valid = 0;
+ if (attr->la_valid & LA_UID)
+ iattr.ia_valid |= ATTR_UID;
+ if (attr->la_valid & LA_GID)
+ iattr.ia_valid |= ATTR_GID;
+ iattr.ia_uid = attr->la_uid;
+ iattr.ia_gid = attr->la_gid;
+ osd_push_ctxt(env, save);
+ rc = ll_vfs_dq_transfer(inode, &iattr) ? -EDQUOT : 0;
+ osd_pop_ctxt(save);
+ if (rc != 0)
+ return rc;
+ }
#endif
-
+ }
cfs_spin_lock(&obj->oo_guard);
rc = osd_inode_setattr(env, inode, attr);
cfs_spin_unlock(&obj->oo_guard);
return rc;
}
-/*
- * Object creation.
- *
- * XXX temporary solution.
- */
-static int osd_create_pre(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
-{
- return 0;
-}
-
-static int osd_create_post(struct osd_thread_info *info, struct osd_object *obj,
- struct lu_attr *attr, struct thandle *th)
-{
- osd_object_init0(obj);
- if (obj->oo_inode && (obj->oo_inode->i_state & I_NEW))
- unlock_new_inode(obj->oo_inode);
- return 0;
-}
-
struct dentry *osd_child_dentry_get(const struct lu_env *env,
struct osd_object *obj,
const char *name, const int namelen)
struct osd_thandle *oth;
const struct dt_index_features *feat = dof->u.dof_idx.di_feat;
- __u32 mode = (attr->la_mode & (S_IFMT | S_IRWXUGO | S_ISVTX));
+ __u32 mode = (attr->la_mode & (S_IFMT | S_IALLUGO | S_ISVTX));
LASSERT(S_ISREG(attr->la_mode));
{
LASSERT(S_ISREG(attr->la_mode));
return osd_mkfile(info, obj, (attr->la_mode &
- (S_IFMT | S_IRWXUGO | S_ISVTX)), hint, th);
+ (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th);
}
static int osd_mksym(struct osd_thread_info *info, struct osd_object *obj,
{
LASSERT(S_ISLNK(attr->la_mode));
return osd_mkfile(info, obj, (attr->la_mode &
- (S_IFMT | S_IRWXUGO | S_ISVTX)), hint, th);
+ (S_IFMT | S_IALLUGO | S_ISVTX)), hint, th);
}
static int osd_mknod(struct osd_thread_info *info, struct osd_object *obj,
struct dt_object_format *dof,
struct thandle *th)
{
- cfs_umode_t mode = attr->la_mode & (S_IFMT | S_IRWXUGO | S_ISVTX);
+ cfs_umode_t mode = attr->la_mode & (S_IFMT | S_IALLUGO | S_ISVTX);
int result;
LINVRNT(osd_invariant(obj));
result = osd_mkfile(info, obj, mode, hint, th);
if (result == 0) {
LASSERT(obj->oo_inode != NULL);
+ /*
+ * This inode should be marked dirty for i_rdev. Currently
+ * that is done in the osd_attr_init().
+ */
init_special_inode(obj->oo_inode, mode, attr->la_rdev);
}
LINVRNT(osd_invariant(obj));
ah->dah_mode = child_mode;
}
+static void osd_attr_init(struct osd_thread_info *info, struct osd_object *obj,
+ struct lu_attr *attr, struct dt_object_format *dof)
+{
+ struct inode *inode = obj->oo_inode;
+ __u64 valid = attr->la_valid;
+ int result;
+
+ attr->la_valid &= ~(LA_TYPE | LA_MODE);
+
+ if (dof->dof_type != DFT_NODE)
+ attr->la_valid &= ~LA_RDEV;
+ if ((valid & LA_ATIME) && (attr->la_atime == LTIME_S(inode->i_atime)))
+ attr->la_valid &= ~LA_ATIME;
+ if ((valid & LA_CTIME) && (attr->la_ctime == LTIME_S(inode->i_ctime)))
+ attr->la_valid &= ~LA_CTIME;
+ if ((valid & LA_MTIME) && (attr->la_mtime == LTIME_S(inode->i_mtime)))
+ attr->la_valid &= ~LA_MTIME;
+
+ if (LDISKFS_HAS_RO_COMPAT_FEATURE(inode->i_sb,
+ LDISKFS_FEATURE_RO_COMPAT_QUOTA)) {
+ result = osd_quota_transfer(inode, attr);
+ if (result)
+ return;
+ } else {
+#ifdef HAVE_QUOTA_SUPPORT
+ attr->la_valid &= ~(LA_UID | LA_GID);
+#endif
+ }
+
+ if (attr->la_valid != 0) {
+ result = osd_inode_setattr(info->oti_env, inode, attr);
+ /*
+ * The osd_inode_setattr() should always succeed here. The
+ * only error that could be returned is EDQUOT when we are
+ * trying to change the UID or GID of the inode. However, this
+ * should not happen since quota enforcement is no longer
+ * enabled on ldiskfs (lquota takes care of it).
+ */
+ LASSERTF(result == 0, "%d", result);
+ inode->i_sb->s_op->dirty_inode(inode);
+ }
+
+ attr->la_valid = valid;
+}
+
/**
* Helper function for osd_object_create()
*
struct dt_object_format *dof,
struct thandle *th)
{
+ int result;
+ __u32 umask;
- int result;
+ /* we drop umask so that permissions we pass are not affected */
+ umask = current->fs->umask;
+ current->fs->umask = 0;
- result = osd_create_pre(info, obj, attr, th);
+ result = osd_create_type_f(dof->dof_type)(info, obj, attr, hint, dof,
+ th);
if (result == 0) {
- result = osd_create_type_f(dof->dof_type)(info, obj,
- attr, hint, dof, th);
- if (result == 0)
- result = osd_create_post(info, obj, attr, th);
+ osd_attr_init(info, obj, attr, dof);
+ osd_object_init0(obj);
+ /* bz 24037 */
+ if (obj->oo_inode && (obj->oo_inode->i_state & I_NEW))
+ unlock_new_inode(obj->oo_inode);
}
+
+ /* restore previous umask value */
+ current->fs->umask = umask;
+
return result;
}
LASSERT(osd_write_locked(env, obj));
LASSERT(th != NULL);
+ if (unlikely(fid_is_acct(fid)))
+ /* Quota files can't be created from the kernel any more,
+ * 'tune2fs -O quota' will take care of creating them */
+ RETURN(-EPERM);
+
OSD_EXEC_OP(th, create);
result = __osd_object_create(info, obj, attr, hint, dof, th);
LASSERT(inode);
LASSERT(!lu_object_is_dying(dt->do_lu.lo_header));
+ if (unlikely(fid_is_acct(fid)))
+ RETURN(-EPERM);
+
/* Parallel control for OI scrub. For most of cases, there is no
* lock contention. So it will not affect unlink performance. */
cfs_mutex_lock(&inode->i_mutex);
LASSERT(osd_write_locked(env, obj));
LASSERT(th != NULL);
+ if (unlikely(fid_is_acct(fid)))
+ /* Quota files can't be created from the kernel any more,
+ * 'tune2fs -O quota' will take care of creating them */
+ RETURN(-EPERM);
+
OSD_EXEC_OP(th, create);
result = __osd_object_create(info, obj, attr, hint, dof, th);
static int osd_index_try(const struct lu_env *env, struct dt_object *dt,
const struct dt_index_features *feat)
{
- int result;
- int ea_dir = 0;
- struct osd_object *obj = osd_dt_obj(dt);
- struct osd_device *osd = osd_obj2dev(obj);
+ int result;
+ int skip_iam = 0;
+ struct osd_object *obj = osd_dt_obj(dt);
+ struct osd_device *osd = osd_obj2dev(obj);
LINVRNT(osd_invariant(obj));
LASSERT(dt_object_exists(dt));
result = 0;
else
result = -ENOTDIR;
- ea_dir = 1;
+ skip_iam = 1;
} else if (unlikely(feat == &dt_otable_features)) {
dt->do_index_ops = &osd_otable_ops;
return 0;
+ } else if (feat == &dt_acct_features) {
+ dt->do_index_ops = &osd_acct_index_ops;
+ result = 0;
+ skip_iam = 1;
} else if (!osd_has_index(obj)) {
struct osd_directory *dir;
result = 0;
}
- if (result == 0 && ea_dir == 0) {
+ if (result == 0 && skip_iam == 0) {
if (!osd_iam_index_probe(env, obj, feat))
result = -ENOTDIR;
}
static int osd_device_init(const struct lu_env *env, struct lu_device *d,
const char *name, struct lu_device *next)
{
- return osd_procfs_init(osd_dev(d), name);
+ struct osd_device *osd = osd_dev(d);
+
+ strncpy(osd->od_svname, name, MAX_OBD_NAME);
+ return osd_procfs_init(osd, name);
}
static int osd_shutdown(const struct lu_env *env, struct osd_device *o)
if (o->od_fsops) {
fsfilt_put_ops(o->od_fsops);
- o->od_fsops = NULL;
+ o->od_fsops = NULL;
+ }
+
+ /* shutdown quota slave instance associated with the device */
+ if (o->od_quota_slave != NULL) {
+ qsd_fini(env, o->od_quota_slave);
+ o->od_quota_slave = NULL;
}
RETURN(0);
if (result < 0)
RETURN(result);
+ /* 2. setup quota slave instance */
+ osd->od_quota_slave = qsd_init(env, osd->od_svname, &osd->od_dt_dev,
+ osd->od_proc_entry);
+ if (IS_ERR(osd->od_quota_slave)) {
+ result = PTR_ERR(osd->od_quota_slave);
+ osd->od_quota_slave = NULL;
+ RETURN(result);
+ }
+
if (!lu_device_is_md(pdev))
RETURN(0);
- /* 2. setup local objects */
+ /* 3. setup local objects */
result = llo_local_objects_setup(env, lu2md_dev(pdev), lu2dt_dev(dev));
RETURN(result);
}