int orh_reserve;
};
-static inline int fsfilt_reserve(struct obd_device *obd,
+/* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
+static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
+ unsigned long max_age)
+{
+ int rc = 0;
+
+ CDEBUG(D_SUPER, "osfs %lu, max_age %lu\n", obd->obd_osfs_age, max_age);
+ if (time_before(obd->obd_osfs_age, max_age)) {
+ rc = obd->obd_fsops->fs_statfs(sb, &obd->obd_osfs);
+ if (rc == 0) /* N.B. statfs can't really fail */
+ obd->obd_osfs_age = jiffies;
+ } else {
+ CDEBUG(D_SUPER, "using cached obd_statfs data\n");
+ }
+
+ return rc;
+}
+
+static inline int fsfilt_reserve(struct obd_device *obd, struct super_block *sb,
int reserve, struct obd_reservation_handle **h)
{
struct obd_reservation_handle *handle;
/* Perform space reservation if needed */
if (reserve) {
- down(&obd->obd_reserve_guard);
+ spin_lock(&obd->obd_osfs_lock);
obd->obd_reserve_freespace_estimated -= reserve;
if (obd->obd_reserve_freespace_estimated < 0) {
- struct obd_statfs osfs;
- /* Can we use jiffies here, or is there a race window
- where somebody calls obd_statfs(), caches data, then
- uses some space, and then we came and get this same
- (now stale) cached data all within same jiffie?
- maybe jiffies-1 should be used? */
- int rc = obd_statfs(obd, &osfs, jiffies);
+ int rc = fsfilt_statfs(obd, sb, jiffies - 1);
if (rc) {
CERROR("statfs failed during reservation\n");
- up(&obd->obd_reserve_guard);
+ spin_unlock(&obd->obd_osfs_lock);
OBD_FREE(handle, sizeof(*handle));
return rc;
}
* available compared to what is really available
* (reiserfs reserves 1996K for itself).
*/
- obd->obd_reserve_freespace_estimated = osfs.os_bavail -
- obd->obd_reserved_space;
+ obd->obd_reserve_freespace_estimated =
+ obd->obd_osfs.os_bfree-obd->obd_reserve_space;
if (obd->obd_reserve_freespace_estimated < reserve) {
- up(&obd->obd_reserve_guard);
+ spin_unlock(&obd->obd_osfs_lock);
OBD_FREE(handle, sizeof(*handle));
return -ENOSPC;
}
obd->obd_reserve_freespace_estimated -= reserve;
}
- obd->obd_reserved_space += reserve;
+ obd->obd_reserve_space += reserve;
handle->orh_reserve = reserve;
- up(&obd->obd_reserve_guard);
+ spin_unlock(&obd->obd_osfs_lock);
}
*h = handle;
return 0;
if (obd->obd_fsops->fs_get_op_len)
reserve = obd->obd_fsops->fs_get_op_len(op, NULL, logs);
- rc = fsfilt_reserve(obd, reserve, &h);
+ rc = fsfilt_reserve(obd, inode->i_sb, reserve, &h);
if (rc)
return ERR_PTR(rc);
return fsfilt_start_log(obd, inode, op, oti, 0);
}
-static inline void *fsfilt_brw_start_log(struct obd_device *obd, int objcount,
+static inline void *fsfilt_brw_start_log(struct obd_device *obd,
+ int objcount,
struct fsfilt_objinfo *fso,
int niocount, struct niobuf_local *nb,
struct obd_trans_info *oti,int numlogs)
if (obd->obd_fsops->fs_get_op_len)
reserve = obd->obd_fsops->fs_get_op_len(objcount, fso, numlogs);
- rc = fsfilt_reserve(obd, reserve, &h);
+ rc = fsfilt_reserve(obd, fso->fso_dentry->d_inode->i_sb, reserve, &h);
if (rc)
return ERR_PTR(rc);
if (time_after(jiffies, now + 15 * HZ))
CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
- down(&obd->obd_reserve_guard);
- obd->obd_reserved_space -= h->orh_reserve;
- LASSERT(obd->obd_reserved_space >= 0);
- up(&obd->obd_reserve_guard);
+ spin_lock(&obd->obd_osfs_lock);
+ obd->obd_reserve_space -= h->orh_reserve;
+ LASSERT(obd->obd_reserve_space >= 0);
+ spin_unlock(&obd->obd_osfs_lock);
OBD_FREE(h, sizeof(*h));
return rc;
if (time_after(jiffies, now + 15 * HZ))
CERROR("long journal start time %lus\n", (jiffies - now) / HZ);
- down(&obd->obd_reserve_guard);
- obd->obd_reserved_space -= h->orh_reserve;
- LASSERT(obd->obd_reserved_space >= 0);
- up(&obd->obd_reserve_guard);
+ spin_lock(&obd->obd_osfs_lock);
+ obd->obd_reserve_space -= h->orh_reserve;
+ LASSERT(obd->obd_reserve_space >= 0);
+ spin_unlock(&obd->obd_osfs_lock);
OBD_FREE(h, sizeof(*h));
return rc;
cb_data);
}
-/* very similar to obd_statfs(), but caller already holds obd_osfs_lock */
-static inline int fsfilt_statfs(struct obd_device *obd, struct super_block *sb,
- unsigned long max_age)
-{
- int rc = 0;
-
- CDEBUG(D_SUPER, "osfs %lu, max_age %lu\n", obd->obd_osfs_age, max_age);
- if (time_before(obd->obd_osfs_age, max_age)) {
- rc = obd->obd_fsops->fs_statfs(sb, &obd->obd_osfs);
- if (rc == 0) /* N.B. statfs can't really fail */
- obd->obd_osfs_age = jiffies;
- } else {
- CDEBUG(D_SUPER, "using cached obd_statfs data\n");
- }
-
- return rc;
-}
-
static inline int fsfilt_sync(struct obd_device *obd, struct super_block *sb)
{
return obd->obd_fsops->fs_sync(sb);
__u64 obd_last_committed;
struct fsfilt_operations *obd_fsops;
spinlock_t obd_osfs_lock;
- struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS];
struct obd_statfs obd_osfs;
unsigned long obd_osfs_age;
struct obd_run_ctxt obd_ctxt;
+ struct llog_ctxt *obd_llog_ctxt[LLOG_MAX_CTXTS];
struct obd_device *obd_observer;
struct obd_export *obd_self_export;
struct proc_dir_entry *obd_svc_procroot;
struct lprocfs_stats *obd_svc_stats;
/* Fields used for fsfilt reservations. */
- int obd_reserved_space;
+ int obd_reserve_space; /* protected by obd_osfs_lock */
/* This field contains cached statfs(2) amount of free blocks,
each time reservation is made, we substract reserved amount from this
field until zero is reached. Then we call statfs(2) again. This
allows to minimize statfs(2) calls on filesystems with lots of free
space. */
long obd_reserve_freespace_estimated;
- struct semaphore obd_reserve_guard;
};
#define OBD_OPT_FORCE 0x0001