* Quota fixes and improvements
[not found] <yes>
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 01/11] quota: Improve locking Jan Kara
2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
` (18 subsequent siblings)
19 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel
I'm sending for review patches fixing some bugs and implementing new quota
features. First four patches fix possible deadlocks in OCFS2 quotas. I plan
to send them to Linus next week if nobody objects. The remaining patches
are going to linux-next and I plan to merge them in the next merge window.
Honza
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 01/11] quota: Improve locking
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
2009-01-24 7:49 ` [PATCH 01/11] quota: Improve locking Andrew Morton
0 siblings, 2 replies; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
We implement dqget() and dqput() that need neither dqonoff_mutex nor dqptr_sem.
Then move dqget() and dqput() calls so that they are not called from under
dqptr_sem. This is important because filesystem callbacks aren't called from
under dqptr_sem which used to cause *lots* of problems with lock ranking
(and with OCFS2 they became close to unsolvable).
The patch also removes two functions which were introduced solely because OCFS2
needed them to cope with the old locking scheme. As time showed, they were not
enough for OCFS2 anyway and it would be unnecessary work to adapt them to the
new locking scheme in which they aren't needed. As a result OCFS2 needs the
following patch to compile properly with quotas. Sorry to any bisecters which
hit this in advance.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/dquot.c | 218 ++++++++++++++++++++++++++--------------------
include/linux/quotaops.h | 2 -
2 files changed, 122 insertions(+), 98 deletions(-)
diff --git a/fs/dquot.c b/fs/dquot.c
index 48c0571..bca3cac 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -87,14 +87,17 @@
#define __DQUOT_PARANOIA
/*
- * There are two quota SMP locks. dq_list_lock protects all lists with quotas
- * and quota formats and also dqstats structure containing statistics about the
- * lists. dq_data_lock protects data from dq_dqb and also mem_dqinfo structures
- * and also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
+ * There are three quota SMP locks. dq_list_lock protects all lists with quotas
+ * and quota formats, dqstats structure containing statistics about the lists
+ * dq_data_lock protects data from dq_dqb and also mem_dqinfo structures and
+ * also guards consistency of dquot->dq_dqb with inode->i_blocks, i_bytes.
* i_blocks and i_bytes updates itself are guarded by i_lock acquired directly
- * in inode_add_bytes() and inode_sub_bytes().
+ * in inode_add_bytes() and inode_sub_bytes(). dq_state_lock protects
+ * modifications of quota state (on quotaon and quotaoff) and readers who care
+ * about latest values take it as well.
*
- * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock
+ * The spinlock ordering is hence: dq_data_lock > dq_list_lock > i_lock,
+ * dq_list_lock > dq_state_lock
*
* Note that some things (eg. sb pointer, type, id) doesn't change during
* the life of the dquot structure and so needn't to be protected by a lock
@@ -103,12 +106,7 @@
* operation is just reading pointers from inode (or not using them at all) the
* read lock is enough. If pointers are altered function must hold write lock
* (these locking rules also apply for S_NOQUOTA flag in the inode - note that
- * for altering the flag i_mutex is also needed). If operation is holding
- * reference to dquot in other way (e.g. quotactl ops) it must be guarded by
- * dqonoff_mutex.
- * This locking assures that:
- * a) update/access to dquot pointers in inode is serialized
- * b) everyone is guarded against invalidate_dquots()
+ * for altering the flag i_mutex is also needed).
*
* Each dquot has its dq_lock mutex. Locked dquots might not be referenced
* from inodes (dquot_alloc_space() and such don't check the dq_lock).
@@ -122,10 +120,17 @@
* Lock ordering (including related VFS locks) is the following:
* i_mutex > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock >
* dqio_mutex
+ * The lock ordering of dqptr_sem imposed by quota code is only dqonoff_sem >
+ * dqptr_sem. But filesystem has to count with the fact that functions such as
+ * dquot_alloc_space() acquire dqptr_sem and they usually have to be called
+ * from inside a transaction to keep filesystem consistency after a crash. Also
+ * filesystems usually want to do some IO on dquot from ->mark_dirty which is
+ * called with dqptr_sem held.
* i_mutex on quota files is special (it's below dqio_mutex)
*/
static DEFINE_SPINLOCK(dq_list_lock);
+static DEFINE_SPINLOCK(dq_state_lock);
DEFINE_SPINLOCK(dq_data_lock);
static char *quotatypes[] = INITQFNAMES;
@@ -428,7 +433,7 @@ static inline void do_destroy_dquot(struct dquot *dquot)
* quota is disabled and pointers from inodes removed so there cannot be new
* quota users. There can still be some users of quotas due to inodes being
* just deleted or pruned by prune_icache() (those are not attached to any
- * list). We have to wait for such users.
+ * list) or parallel quotactl call. We have to wait for such users.
*/
static void invalidate_dquots(struct super_block *sb, int type)
{
@@ -600,7 +605,6 @@ static struct shrinker dqcache_shrinker = {
/*
* Put reference to dquot
* NOTE: If you change this function please check whether dqput_blocks() works right...
- * MUST be called with either dqptr_sem or dqonoff_mutex held
*/
void dqput(struct dquot *dquot)
{
@@ -697,36 +701,30 @@ static struct dquot *get_empty_dquot(struct super_block *sb, int type)
}
/*
- * Check whether dquot is in memory.
- * MUST be called with either dqptr_sem or dqonoff_mutex held
- */
-int dquot_is_cached(struct super_block *sb, unsigned int id, int type)
-{
- unsigned int hashent = hashfn(sb, id, type);
- int ret = 0;
-
- if (!sb_has_quota_active(sb, type))
- return 0;
- spin_lock(&dq_list_lock);
- if (find_dquot(hashent, sb, id, type) != NODQUOT)
- ret = 1;
- spin_unlock(&dq_list_lock);
- return ret;
-}
-
-/*
* Get reference to dquot
- * MUST be called with either dqptr_sem or dqonoff_mutex held
+ *
+ * Locking is slightly tricky here. We are guarded from parallel quotaoff()
+ * destroying our dquot by:
+ * a) checking for quota flags under dq_list_lock and
+ * b) getting a reference to dquot before we release dq_list_lock
*/
struct dquot *dqget(struct super_block *sb, unsigned int id, int type)
{
unsigned int hashent = hashfn(sb, id, type);
- struct dquot *dquot, *empty = NODQUOT;
+ struct dquot *dquot = NODQUOT, *empty = NODQUOT;
if (!sb_has_quota_active(sb, type))
return NODQUOT;
we_slept:
spin_lock(&dq_list_lock);
+ spin_lock(&dq_state_lock);
+ if (!sb_has_quota_active(sb, type)) {
+ spin_unlock(&dq_state_lock);
+ spin_unlock(&dq_list_lock);
+ goto out;
+ }
+ spin_unlock(&dq_state_lock);
+
if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) {
if (empty == NODQUOT) {
spin_unlock(&dq_list_lock);
@@ -735,6 +733,7 @@ we_slept:
goto we_slept;
}
dquot = empty;
+ empty = NODQUOT;
dquot->dq_id = id;
/* all dquots go on the inuse_list */
put_inuse(dquot);
@@ -749,8 +748,6 @@ we_slept:
dqstats.cache_hits++;
dqstats.lookups++;
spin_unlock(&dq_list_lock);
- if (empty)
- do_destroy_dquot(empty);
}
/* Wait for dq_lock - after this we know that either dquot_release() is already
* finished or it will be canceled due to dq_count > 1 test */
@@ -758,11 +755,15 @@ we_slept:
/* Read the dquot and instantiate it (everything done only if needed) */
if (!test_bit(DQ_ACTIVE_B, &dquot->dq_flags) && sb->dq_op->acquire_dquot(dquot) < 0) {
dqput(dquot);
- return NODQUOT;
+ dquot = NODQUOT;
+ goto out;
}
#ifdef __DQUOT_PARANOIA
BUG_ON(!dquot->dq_sb); /* Has somebody invalidated entry under us? */
#endif
+out:
+ if (empty)
+ do_destroy_dquot(empty);
return dquot;
}
@@ -1198,63 +1199,76 @@ static int info_bdq_free(struct dquot *dquot, qsize_t space)
}
/*
* Initialize quota pointers in inode
- * Transaction must be started at entry
+ * We do things in a bit complicated way but by that we avoid calling
+ * dqget() and thus filesystem callbacks under dqptr_sem.
*/
int dquot_initialize(struct inode *inode, int type)
{
unsigned int id = 0;
int cnt, ret = 0;
+ struct dquot *got[MAXQUOTAS] = { NODQUOT, NODQUOT };
+ struct super_block *sb = inode->i_sb;
/* First test before acquiring mutex - solves deadlocks when we
* re-enter the quota code and are already holding the mutex */
if (IS_NOQUOTA(inode))
return 0;
- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
+ /* First get references to structures we might need. */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (type != -1 && cnt != type)
+ continue;
+ switch (cnt) {
+ case USRQUOTA:
+ id = inode->i_uid;
+ break;
+ case GRPQUOTA:
+ id = inode->i_gid;
+ break;
+ }
+ got[cnt] = dqget(sb, id, cnt);
+ }
+
+ down_write(&sb_dqopt(sb)->dqptr_sem);
/* Having dqptr_sem we know NOQUOTA flags can't be altered... */
if (IS_NOQUOTA(inode))
goto out_err;
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
+ /* Avoid races with quotaoff() */
+ if (!sb_has_quota_active(sb, cnt))
+ continue;
if (inode->i_dquot[cnt] == NODQUOT) {
- switch (cnt) {
- case USRQUOTA:
- id = inode->i_uid;
- break;
- case GRPQUOTA:
- id = inode->i_gid;
- break;
- }
- inode->i_dquot[cnt] = dqget(inode->i_sb, id, cnt);
+ inode->i_dquot[cnt] = got[cnt];
+ got[cnt] = NODQUOT;
}
}
out_err:
- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ up_write(&sb_dqopt(sb)->dqptr_sem);
+ /* Drop unused references */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ dqput(got[cnt]);
return ret;
}
/*
* Release all quotas referenced by inode
- * Transaction must be started at an entry
*/
-int dquot_drop_locked(struct inode *inode)
+int dquot_drop(struct inode *inode)
{
int cnt;
+ struct dquot *put[MAXQUOTAS];
+ down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] != NODQUOT) {
- dqput(inode->i_dquot[cnt]);
- inode->i_dquot[cnt] = NODQUOT;
- }
+ put[cnt] = inode->i_dquot[cnt];
+ inode->i_dquot[cnt] = NODQUOT;
}
- return 0;
-}
-
-int dquot_drop(struct inode *inode)
-{
- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
- dquot_drop_locked(inode);
up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ dqput(put[cnt]);
return 0;
}
@@ -1470,8 +1484,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
qsize_t space;
struct dquot *transfer_from[MAXQUOTAS];
struct dquot *transfer_to[MAXQUOTAS];
- int cnt, ret = NO_QUOTA, chuid = (iattr->ia_valid & ATTR_UID) && inode->i_uid != iattr->ia_uid,
- chgid = (iattr->ia_valid & ATTR_GID) && inode->i_gid != iattr->ia_gid;
+ int cnt, ret = QUOTA_OK;
+ int chuid = iattr->ia_valid & ATTR_UID && inode->i_uid != iattr->ia_uid,
+ chgid = iattr->ia_valid & ATTR_GID && inode->i_gid != iattr->ia_gid;
char warntype_to[MAXQUOTAS];
char warntype_from_inodes[MAXQUOTAS], warntype_from_space[MAXQUOTAS];
@@ -1479,21 +1494,11 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
* re-enter the quota code and are already holding the mutex */
if (IS_NOQUOTA(inode))
return QUOTA_OK;
- /* Clear the arrays */
+ /* Initialize the arrays */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- transfer_to[cnt] = transfer_from[cnt] = NODQUOT;
+ transfer_from[cnt] = NODQUOT;
+ transfer_to[cnt] = NODQUOT;
warntype_to[cnt] = QUOTA_NL_NOWARN;
- }
- down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
- /* Now recheck reliably when holding dqptr_sem */
- if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
- return QUOTA_OK;
- }
- /* First build the transfer_to list - here we can block on
- * reading/instantiating of dquots. We know that the transaction for
- * us was already started so we don't violate lock ranking here */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
switch (cnt) {
case USRQUOTA:
if (!chuid)
@@ -1507,6 +1512,13 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
break;
}
}
+
+ down_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ /* Now recheck reliably when holding dqptr_sem */
+ if (IS_NOQUOTA(inode)) { /* File without quota accounting? */
+ up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ goto put_all;
+ }
spin_lock(&dq_data_lock);
space = inode_get_bytes(inode);
/* Build the transfer_from list and check the limits */
@@ -1517,7 +1529,7 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
if (check_idq(transfer_to[cnt], 1, warntype_to + cnt) ==
NO_QUOTA || check_bdq(transfer_to[cnt], space, 0,
warntype_to + cnt) == NO_QUOTA)
- goto warn_put_all;
+ goto over_quota;
}
/*
@@ -1545,28 +1557,37 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
inode->i_dquot[cnt] = transfer_to[cnt];
}
- ret = QUOTA_OK;
-warn_put_all:
spin_unlock(&dq_data_lock);
+ up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+
/* Dirtify all the dquots - this can block when journalling */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (transfer_from[cnt])
mark_dquot_dirty(transfer_from[cnt]);
- if (transfer_to[cnt])
+ if (transfer_to[cnt]) {
mark_dquot_dirty(transfer_to[cnt]);
+ /* The reference we got is transferred to the inode */
+ transfer_to[cnt] = NODQUOT;
+ }
}
+warn_put_all:
flush_warnings(transfer_to, warntype_to);
flush_warnings(transfer_from, warntype_from_inodes);
flush_warnings(transfer_from, warntype_from_space);
-
+put_all:
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (ret == QUOTA_OK && transfer_from[cnt] != NODQUOT)
- dqput(transfer_from[cnt]);
- if (ret == NO_QUOTA && transfer_to[cnt] != NODQUOT)
- dqput(transfer_to[cnt]);
+ dqput(transfer_from[cnt]);
+ dqput(transfer_to[cnt]);
}
- up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
return ret;
+over_quota:
+ spin_unlock(&dq_data_lock);
+ up_write(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ /* Clear dquot pointers we don't want to dqput() */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ transfer_from[cnt] = NODQUOT;
+ ret = NO_QUOTA;
+ goto warn_put_all;
}
/* Wrapper for transferring ownership of an inode */
@@ -1651,19 +1672,24 @@ int vfs_quota_disable(struct super_block *sb, int type, unsigned int flags)
continue;
if (flags & DQUOT_SUSPENDED) {
+ spin_lock(&dq_state_lock);
dqopt->flags |=
dquot_state_flag(DQUOT_SUSPENDED, cnt);
+ spin_unlock(&dq_state_lock);
} else {
+ spin_lock(&dq_state_lock);
dqopt->flags &= ~dquot_state_flag(flags, cnt);
/* Turning off suspended quotas? */
if (!sb_has_quota_loaded(sb, cnt) &&
sb_has_quota_suspended(sb, cnt)) {
dqopt->flags &= ~dquot_state_flag(
DQUOT_SUSPENDED, cnt);
+ spin_unlock(&dq_state_lock);
iput(dqopt->files[cnt]);
dqopt->files[cnt] = NULL;
continue;
}
+ spin_unlock(&dq_state_lock);
}
/* We still have to keep quota loaded? */
@@ -1830,7 +1856,9 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id,
}
mutex_unlock(&dqopt->dqio_mutex);
mutex_unlock(&inode->i_mutex);
+ spin_lock(&dq_state_lock);
dqopt->flags |= dquot_state_flag(flags, type);
+ spin_unlock(&dq_state_lock);
add_dquot_ref(sb, type);
mutex_unlock(&dqopt->dqonoff_mutex);
@@ -1872,9 +1900,11 @@ static int vfs_quota_on_remount(struct super_block *sb, int type)
}
inode = dqopt->files[type];
dqopt->files[type] = NULL;
+ spin_lock(&dq_state_lock);
flags = dqopt->flags & dquot_state_flag(DQUOT_USAGE_ENABLED |
DQUOT_LIMITS_ENABLED, type);
dqopt->flags &= ~dquot_state_flag(DQUOT_STATE_FLAGS, type);
+ spin_unlock(&dq_state_lock);
mutex_unlock(&dqopt->dqonoff_mutex);
flags = dquot_generic_flag(flags, type);
@@ -1952,7 +1982,9 @@ int vfs_quota_enable(struct inode *inode, int type, int format_id,
ret = -EBUSY;
goto out_lock;
}
+ spin_lock(&dq_state_lock);
sb_dqopt(sb)->flags |= dquot_state_flag(flags, type);
+ spin_unlock(&dq_state_lock);
out_lock:
mutex_unlock(&dqopt->dqonoff_mutex);
return ret;
@@ -2039,14 +2071,12 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
{
struct dquot *dquot;
- mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
- if (!(dquot = dqget(sb, id, type))) {
- mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+ dquot = dqget(sb, id, type);
+ if (dquot == NODQUOT)
return -ESRCH;
- }
do_get_dqblk(dquot, di);
dqput(dquot);
- mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
+
return 0;
}
@@ -2130,7 +2160,6 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
struct dquot *dquot;
int rc;
- mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
dquot = dqget(sb, id, type);
if (!dquot) {
rc = -ESRCH;
@@ -2139,7 +2168,6 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
rc = do_set_dqblk(dquot, di);
dqput(dquot);
out:
- mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
return rc;
}
@@ -2370,11 +2398,9 @@ EXPORT_SYMBOL(dquot_release);
EXPORT_SYMBOL(dquot_mark_dquot_dirty);
EXPORT_SYMBOL(dquot_initialize);
EXPORT_SYMBOL(dquot_drop);
-EXPORT_SYMBOL(dquot_drop_locked);
EXPORT_SYMBOL(vfs_dq_drop);
EXPORT_SYMBOL(dqget);
EXPORT_SYMBOL(dqput);
-EXPORT_SYMBOL(dquot_is_cached);
EXPORT_SYMBOL(dquot_alloc_space);
EXPORT_SYMBOL(dquot_alloc_inode);
EXPORT_SYMBOL(dquot_free_space);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 21b781a..0b35b3a 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -24,10 +24,8 @@ void sync_dquots(struct super_block *sb, int type);
int dquot_initialize(struct inode *inode, int type);
int dquot_drop(struct inode *inode);
-int dquot_drop_locked(struct inode *inode);
struct dquot *dqget(struct super_block *sb, unsigned int id, int type);
void dqput(struct dquot *dquot);
-int dquot_is_cached(struct super_block *sb, unsigned int id, int type);
int dquot_scan_active(struct super_block *sb,
int (*fn)(struct dquot *dquot, unsigned long priv),
unsigned long priv);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop()
2009-01-16 18:08 ` [PATCH 01/11] quota: Improve locking Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
2009-01-24 7:49 ` [PATCH 01/11] quota: Improve locking Andrew Morton
1 sibling, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
Since ->acquire_dquot and ->release_dquot callbacks aren't called under
dqptr_sem anymore, we don't have to start a transaction and obtain locks
so early. So we can just remove all this complicated stuff.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ocfs2/quota_global.c | 169 +----------------------------------------------
1 files changed, 2 insertions(+), 167 deletions(-)
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 6aff8f2..f4efa89 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -810,171 +810,6 @@ out:
return status;
}
-/* This is difficult. We have to lock quota inode and start transaction
- * in this function but we don't want to take the penalty of exlusive
- * quota file lock when we are just going to use cached structures. So
- * we just take read lock check whether we have dquot cached and if so,
- * we don't have to take the write lock... */
-static int ocfs2_dquot_initialize(struct inode *inode, int type)
-{
- handle_t *handle = NULL;
- int status = 0;
- struct super_block *sb = inode->i_sb;
- struct ocfs2_mem_dqinfo *oinfo;
- int exclusive = 0;
- int cnt;
- qid_t id;
-
- mlog_entry_void();
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (type != -1 && cnt != type)
- continue;
- if (!sb_has_quota_active(sb, cnt))
- continue;
- oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
- status = ocfs2_lock_global_qf(oinfo, 0);
- if (status < 0)
- goto out;
- /* This is just a performance optimization not a reliable test.
- * Since we hold an inode lock, noone can actually release
- * the structure until we are finished with initialization. */
- if (inode->i_dquot[cnt] != NODQUOT) {
- ocfs2_unlock_global_qf(oinfo, 0);
- continue;
- }
- /* When we have inode lock, we know that no dquot_release() can
- * run and thus we can safely check whether we need to
- * read+modify global file to get quota information or whether
- * our node already has it. */
- if (cnt == USRQUOTA)
- id = inode->i_uid;
- else if (cnt == GRPQUOTA)
- id = inode->i_gid;
- else
- BUG();
- /* Obtain exclusion from quota off... */
- down_write(&sb_dqopt(sb)->dqptr_sem);
- exclusive = !dquot_is_cached(sb, id, cnt);
- up_write(&sb_dqopt(sb)->dqptr_sem);
- if (exclusive) {
- status = ocfs2_lock_global_qf(oinfo, 1);
- if (status < 0) {
- exclusive = 0;
- mlog_errno(status);
- goto out_ilock;
- }
- handle = ocfs2_start_trans(OCFS2_SB(sb),
- ocfs2_calc_qinit_credits(sb, cnt));
- if (IS_ERR(handle)) {
- status = PTR_ERR(handle);
- mlog_errno(status);
- goto out_ilock;
- }
- }
- dquot_initialize(inode, cnt);
- if (exclusive) {
- ocfs2_commit_trans(OCFS2_SB(sb), handle);
- ocfs2_unlock_global_qf(oinfo, 1);
- }
- ocfs2_unlock_global_qf(oinfo, 0);
- }
- mlog_exit(0);
- return 0;
-out_ilock:
- if (exclusive)
- ocfs2_unlock_global_qf(oinfo, 1);
- ocfs2_unlock_global_qf(oinfo, 0);
-out:
- mlog_exit(status);
- return status;
-}
-
-static int ocfs2_dquot_drop_slow(struct inode *inode)
-{
- int status = 0;
- int cnt;
- int got_lock[MAXQUOTAS] = {0, 0};
- handle_t *handle;
- struct super_block *sb = inode->i_sb;
- struct ocfs2_mem_dqinfo *oinfo;
-
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (!sb_has_quota_active(sb, cnt))
- continue;
- oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
- status = ocfs2_lock_global_qf(oinfo, 1);
- if (status < 0)
- goto out;
- got_lock[cnt] = 1;
- }
- handle = ocfs2_start_trans(OCFS2_SB(sb),
- ocfs2_calc_qinit_credits(sb, USRQUOTA) +
- ocfs2_calc_qinit_credits(sb, GRPQUOTA));
- if (IS_ERR(handle)) {
- status = PTR_ERR(handle);
- mlog_errno(status);
- goto out;
- }
- dquot_drop(inode);
- ocfs2_commit_trans(OCFS2_SB(sb), handle);
-out:
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- if (got_lock[cnt]) {
- oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
- ocfs2_unlock_global_qf(oinfo, 1);
- }
- return status;
-}
-
-/* See the comment before ocfs2_dquot_initialize. */
-static int ocfs2_dquot_drop(struct inode *inode)
-{
- int status = 0;
- struct super_block *sb = inode->i_sb;
- struct ocfs2_mem_dqinfo *oinfo;
- int exclusive = 0;
- int cnt;
- int got_lock[MAXQUOTAS] = {0, 0};
-
- mlog_entry_void();
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (!sb_has_quota_active(sb, cnt))
- continue;
- oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
- status = ocfs2_lock_global_qf(oinfo, 0);
- if (status < 0)
- goto out;
- got_lock[cnt] = 1;
- }
- /* Lock against anyone releasing references so that when when we check
- * we know we are not going to be last ones to release dquot */
- down_write(&sb_dqopt(sb)->dqptr_sem);
- /* Urgh, this is a terrible hack :( */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
- if (inode->i_dquot[cnt] != NODQUOT &&
- atomic_read(&inode->i_dquot[cnt]->dq_count) > 1) {
- exclusive = 1;
- break;
- }
- }
- if (!exclusive)
- dquot_drop_locked(inode);
- up_write(&sb_dqopt(sb)->dqptr_sem);
-out:
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- if (got_lock[cnt]) {
- oinfo = sb_dqinfo(sb, cnt)->dqi_priv;
- ocfs2_unlock_global_qf(oinfo, 0);
- }
- /* In case we bailed out because we had to do expensive locking
- * do it now... */
- if (exclusive)
- status = ocfs2_dquot_drop_slow(inode);
- mlog_exit(status);
- return status;
-}
-
static struct dquot *ocfs2_alloc_dquot(struct super_block *sb, int type)
{
struct ocfs2_dquot *dquot =
@@ -991,8 +826,8 @@ static void ocfs2_destroy_dquot(struct dquot *dquot)
}
struct dquot_operations ocfs2_quota_operations = {
- .initialize = ocfs2_dquot_initialize,
- .drop = ocfs2_dquot_drop,
+ .initialize = dquot_initialize,
+ .drop = dquot_drop,
.alloc_space = dquot_alloc_space,
.alloc_inode = dquot_alloc_inode,
.free_space = dquot_free_space,
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq
2009-01-16 18:08 ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
Dropping of last reference to dentry lock is a complicated operation involving
dropping of reference to inode. This can get complicated and quota code in
particular needs to obtain some quota locks which leads to potential deadlock.
Thus we defer dropping of inode reference to ocfs2_wq.
Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Mark Fasheh <mfasheh@suse.de>
---
fs/ocfs2/dcache.c | 42 +++++++++++++++++++++++++++++++++++++++---
fs/ocfs2/dcache.h | 9 ++++++++-
fs/ocfs2/ocfs2.h | 6 ++++++
fs/ocfs2/super.c | 3 +++
4 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c
index b1cc7c3..e9d7c20 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -38,6 +38,7 @@
#include "dlmglue.h"
#include "file.h"
#include "inode.h"
+#include "super.h"
static int ocfs2_dentry_revalidate(struct dentry *dentry,
@@ -294,6 +295,34 @@ out_attach:
return ret;
}
+static DEFINE_SPINLOCK(dentry_list_lock);
+
+/* We limit the number of dentry locks to drop in one go. We have
+ * this limit so that we don't starve other users of ocfs2_wq. */
+#define DL_INODE_DROP_COUNT 64
+
+/* Drop inode references from dentry locks */
+void ocfs2_drop_dl_inodes(struct work_struct *work)
+{
+ struct ocfs2_super *osb = container_of(work, struct ocfs2_super,
+ dentry_lock_work);
+ struct ocfs2_dentry_lock *dl;
+ int drop_count = DL_INODE_DROP_COUNT;
+
+ spin_lock(&dentry_list_lock);
+ while (osb->dentry_lock_list && drop_count--) {
+ dl = osb->dentry_lock_list;
+ osb->dentry_lock_list = dl->dl_next;
+ spin_unlock(&dentry_list_lock);
+ iput(dl->dl_inode);
+ kfree(dl);
+ spin_lock(&dentry_list_lock);
+ }
+ if (osb->dentry_lock_list)
+ queue_work(ocfs2_wq, &osb->dentry_lock_work);
+ spin_unlock(&dentry_list_lock);
+}
+
/*
* ocfs2_dentry_iput() and friends.
*
@@ -318,16 +347,23 @@ out_attach:
static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl)
{
- iput(dl->dl_inode);
ocfs2_simple_drop_lockres(osb, &dl->dl_lockres);
ocfs2_lock_res_free(&dl->dl_lockres);
- kfree(dl);
+
+ /* We leave dropping of inode reference to ocfs2_wq as that can
+ * possibly lead to inode deletion which gets tricky */
+ spin_lock(&dentry_list_lock);
+ if (!osb->dentry_lock_list)
+ queue_work(ocfs2_wq, &osb->dentry_lock_work);
+ dl->dl_next = osb->dentry_lock_list;
+ osb->dentry_lock_list = dl;
+ spin_unlock(&dentry_list_lock);
}
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl)
{
- int unlock = 0;
+ int unlock;
BUG_ON(dl->dl_count == 0);
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h
index c091c34..d06e16c 100644
--- a/fs/ocfs2/dcache.h
+++ b/fs/ocfs2/dcache.h
@@ -29,8 +29,13 @@
extern struct dentry_operations ocfs2_dentry_ops;
struct ocfs2_dentry_lock {
+ /* Use count of dentry lock */
unsigned int dl_count;
- u64 dl_parent_blkno;
+ union {
+ /* Linked list of dentry locks to release */
+ struct ocfs2_dentry_lock *dl_next;
+ u64 dl_parent_blkno;
+ };
/*
* The ocfs2_dentry_lock keeps an inode reference until
@@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode,
void ocfs2_dentry_lock_put(struct ocfs2_super *osb,
struct ocfs2_dentry_lock *dl);
+void ocfs2_drop_dl_inodes(struct work_struct *work);
+
struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno,
int skip_unhashed);
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index ad5c24a..0773841 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -210,6 +210,7 @@ struct ocfs2_journal;
struct ocfs2_slot_info;
struct ocfs2_recovery_map;
struct ocfs2_quota_recovery;
+struct ocfs2_dentry_lock;
struct ocfs2_super
{
struct task_struct *commit_task;
@@ -325,6 +326,11 @@ struct ocfs2_super
struct list_head blocked_lock_list;
unsigned long blocked_lock_count;
+ /* List of dentry locks to release. Anyone can add locks to
+ * the list, ocfs2_wq processes the list */
+ struct ocfs2_dentry_lock *dentry_lock_list;
+ struct work_struct dentry_lock_work;
+
wait_queue_head_t osb_mount_event;
/* Truncate log info */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 43ed113..b1cb38f 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery);
journal->j_state = OCFS2_JOURNAL_FREE;
+ INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes);
+ osb->dentry_lock_list = NULL;
+
/* get some pseudo constants for clustersize bits */
osb->s_clustersize_bits =
le32_to_cpu(di->id2.i_super.s_clustersize_bits);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot()
2009-01-16 18:08 ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
It could happen that some limit has been set via quotactl() and in parallel
->mark_dirty() is called from another thread doing e.g. dquot_alloc_space(). In
such case ocfs2_write_dquot() must not try to sync the dquot because that needs
global quota lock but that ranks above transaction start.
Signed-off-by: Jan Kara <jack@suse.cz>
Acked-by: Mark Fasheh <mfasheh@suse.de>
---
fs/ocfs2/quota_global.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index f4efa89..1ed0f7c 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot)
if (dquot->dq_flags & mask)
sync = 1;
spin_unlock(&dq_data_lock);
- if (!sync) {
+ /* This is a slight hack but we can't afford getting global quota
+ * lock if we already have a transaction started. */
+ if (!sync || journal_current_handle()) {
status = ocfs2_write_dquot(dquot);
goto out;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 05/11] quota: Add quota reservation support
2009-01-16 18:08 ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara
From: Mingming Cao <cmm@us.ibm.com>
Delayed allocation defers the block allocation at the dirty pages
flush-out time, doing quota charge/check at that time is too late.
But we can't charge the quota blocks until blocks are really allocated,
otherwise users could get overcharged after reboot from system crash.
This patch adds quota reservation for delayed allocation. Quota blocks
are reserved in memory, inode and quota won't gets dirtied until later
block allocation time.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/dquot.c | 117 +++++++++++++++++++++++++++++++++------------
include/linux/quota.h | 3 +
include/linux/quotaops.h | 21 ++++++++
3 files changed, 110 insertions(+), 31 deletions(-)
diff --git a/fs/dquot.c b/fs/dquot.c
index bca3cac..9b1c4d3 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -899,6 +899,11 @@ static inline void dquot_incr_space(struct dquot *dquot, qsize_t number)
dquot->dq_dqb.dqb_curspace += number;
}
+static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
+{
+ dquot->dq_dqb.dqb_rsvspace += number;
+}
+
static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
{
if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1068,7 +1073,11 @@ err_out:
kfree_skb(skb);
}
#endif
-
+/*
+ * Write warnings to the console and send warning messages over netlink.
+ *
+ * Note that this function can sleep.
+ */
static inline void flush_warnings(struct dquot * const *dquots, char *warntype)
{
int i;
@@ -1129,13 +1138,18 @@ static int check_idq(struct dquot *dquot, qsize_t inodes, char *warntype)
/* needs dq_data_lock */
static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *warntype)
{
+ qsize_t tspace;
+
*warntype = QUOTA_NL_NOWARN;
if (!sb_has_quota_limits_enabled(dquot->dq_sb, dquot->dq_type) ||
test_bit(DQ_FAKE_B, &dquot->dq_flags))
return QUOTA_OK;
+ tspace = dquot->dq_dqb.dqb_curspace + dquot->dq_dqb.dqb_rsvspace
+ + space;
+
if (dquot->dq_dqb.dqb_bhardlimit &&
- dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bhardlimit &&
+ tspace > dquot->dq_dqb.dqb_bhardlimit &&
!ignore_hardlimit(dquot)) {
if (!prealloc)
*warntype = QUOTA_NL_BHARDWARN;
@@ -1143,7 +1157,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
}
if (dquot->dq_dqb.dqb_bsoftlimit &&
- dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+ tspace > dquot->dq_dqb.dqb_bsoftlimit &&
dquot->dq_dqb.dqb_btime && get_seconds() >= dquot->dq_dqb.dqb_btime &&
!ignore_hardlimit(dquot)) {
if (!prealloc)
@@ -1152,7 +1166,7 @@ static int check_bdq(struct dquot *dquot, qsize_t space, int prealloc, char *war
}
if (dquot->dq_dqb.dqb_bsoftlimit &&
- dquot->dq_dqb.dqb_curspace + space > dquot->dq_dqb.dqb_bsoftlimit &&
+ tspace > dquot->dq_dqb.dqb_bsoftlimit &&
dquot->dq_dqb.dqb_btime == 0) {
if (!prealloc) {
*warntype = QUOTA_NL_BSOFTWARN;
@@ -1306,51 +1320,92 @@ void vfs_dq_drop(struct inode *inode)
/*
* This operation can block, but only after everything is updated
*/
-int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+int __dquot_alloc_space(struct inode *inode, qsize_t number,
+ int warn, int reserve)
{
- int cnt, ret = NO_QUOTA;
+ int cnt, ret = QUOTA_OK;
char warntype[MAXQUOTAS];
- /* First test before acquiring mutex - solves deadlocks when we
- * re-enter the quota code and are already holding the mutex */
- if (IS_NOQUOTA(inode)) {
-out_add:
- inode_add_bytes(inode, number);
- return QUOTA_OK;
- }
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
warntype[cnt] = QUOTA_NL_NOWARN;
- down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
- if (IS_NOQUOTA(inode)) { /* Now we can do reliable test... */
- up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
- goto out_add;
- }
spin_lock(&dq_data_lock);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
continue;
- if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt) == NO_QUOTA)
- goto warn_put_all;
+ if (check_bdq(inode->i_dquot[cnt], number, warn, warntype+cnt)
+ == NO_QUOTA) {
+ ret = NO_QUOTA;
+ goto out_unlock;
+ }
}
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (inode->i_dquot[cnt] == NODQUOT)
continue;
- dquot_incr_space(inode->i_dquot[cnt], number);
+ if (reserve)
+ dquot_resv_space(inode->i_dquot[cnt], number);
+ else
+ dquot_incr_space(inode->i_dquot[cnt], number);
}
- inode_add_bytes(inode, number);
- ret = QUOTA_OK;
-warn_put_all:
+ if (!reserve)
+ inode_add_bytes(inode, number);
+out_unlock:
spin_unlock(&dq_data_lock);
- if (ret == QUOTA_OK)
- /* Dirtify all the dquots - this can block when journalling */
- for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- if (inode->i_dquot[cnt])
- mark_dquot_dirty(inode->i_dquot[cnt]);
flush_warnings(inode->i_dquot, warntype);
+ return ret;
+}
+
+int dquot_alloc_space(struct inode *inode, qsize_t number, int warn)
+{
+ int cnt, ret = QUOTA_OK;
+
+ /*
+ * First test before acquiring mutex - solves deadlocks when we
+ * re-enter the quota code and are already holding the mutex
+ */
+ if (IS_NOQUOTA(inode)) {
+ inode_add_bytes(inode, number);
+ goto out;
+ }
+
+ down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ inode_add_bytes(inode, number);
+ goto out_unlock;
+ }
+
+ ret = __dquot_alloc_space(inode, number, warn, 0);
+ if (ret == NO_QUOTA)
+ goto out_unlock;
+
+ /* Dirtify all the dquots - this can block when journalling */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (inode->i_dquot[cnt])
+ mark_dquot_dirty(inode->i_dquot[cnt]);
+out_unlock:
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+ return ret;
+}
+
+int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
+{
+ int ret = QUOTA_OK;
+
+ if (IS_NOQUOTA(inode))
+ goto out;
+
+ down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode))
+ goto out_unlock;
+
+ ret = __dquot_alloc_space(inode, number, warn, 1);
+out_unlock:
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
return ret;
}
+EXPORT_SYMBOL(dquot_reserve_space);
/*
* This operation can block, but only after everything is updated
@@ -2057,7 +2112,7 @@ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di)
spin_lock(&dq_data_lock);
di->dqb_bhardlimit = stoqb(dm->dqb_bhardlimit);
di->dqb_bsoftlimit = stoqb(dm->dqb_bsoftlimit);
- di->dqb_curspace = dm->dqb_curspace;
+ di->dqb_curspace = dm->dqb_curspace + dm->dqb_rsvspace;
di->dqb_ihardlimit = dm->dqb_ihardlimit;
di->dqb_isoftlimit = dm->dqb_isoftlimit;
di->dqb_curinodes = dm->dqb_curinodes;
@@ -2097,7 +2152,7 @@ static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
spin_lock(&dq_data_lock);
if (di->dqb_valid & QIF_SPACE) {
- dm->dqb_curspace = di->dqb_curspace;
+ dm->dqb_curspace = di->dqb_curspace - dm->dqb_rsvspace;
check_blim = 1;
__set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
}
diff --git a/include/linux/quota.h b/include/linux/quota.h
index d72d5d8..54b837f 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -198,6 +198,7 @@ struct mem_dqblk {
qsize_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
qsize_t dqb_bsoftlimit; /* preferred limit on disk blks */
qsize_t dqb_curspace; /* current used space */
+ qsize_t dqb_rsvspace; /* current reserved space for delalloc*/
qsize_t dqb_ihardlimit; /* absolute limit on allocated inodes */
qsize_t dqb_isoftlimit; /* preferred inode limit */
qsize_t dqb_curinodes; /* current # allocated inodes */
@@ -308,6 +309,8 @@ struct dquot_operations {
int (*release_dquot) (struct dquot *); /* Quota is going to be deleted from disk */
int (*mark_dirty) (struct dquot *); /* Dquot is marked dirty */
int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */
+ /* reserve quota for delayed block allocation */
+ int (*reserve_space) (struct inode *, qsize_t, int);
};
/* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 0b35b3a..3e3a0d2 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -183,6 +183,16 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
return ret;
}
+static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
+{
+ if (sb_any_quota_active(inode->i_sb)) {
+ /* Used space is updated in alloc_space() */
+ if (inode->i_sb->dq_op->reserve_space(inode, nr, 0) == NO_QUOTA)
+ return 1;
+ }
+ return 0;
+}
+
static inline int vfs_dq_alloc_inode(struct inode *inode)
{
if (sb_any_quota_active(inode->i_sb)) {
@@ -339,6 +349,11 @@ static inline int vfs_dq_alloc_space(struct inode *inode, qsize_t nr)
return 0;
}
+static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
+{
+ return 0;
+}
+
static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
{
inode_sub_bytes(inode, nr);
@@ -376,6 +391,12 @@ static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
nr << inode->i_sb->s_blocksize_bits);
}
+static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
+{
+ return vfs_dq_reserve_space(inode,
+ nr << inode->i_blkbits);
+}
+
static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
{
vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 06/11] quota: Add quota reservation claim and released operations
2009-01-16 18:08 ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara
From: Mingming Cao <cmm@us.ibm.com>
Reserved quota will be claimed at the block allocation time. Over-booked
quota could be returned back with the release callback function.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/dquot.c | 110 ++++++++++++++++++++++++++++++++++++++++++++--
include/linux/quota.h | 6 +++
include/linux/quotaops.h | 53 ++++++++++++++++++++++
3 files changed, 165 insertions(+), 4 deletions(-)
diff --git a/fs/dquot.c b/fs/dquot.c
index 9b1c4d3..2916f91 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -904,6 +904,23 @@ static inline void dquot_resv_space(struct dquot *dquot, qsize_t number)
dquot->dq_dqb.dqb_rsvspace += number;
}
+/*
+ * Claim reserved quota space
+ */
+static void dquot_claim_reserved_space(struct dquot *dquot,
+ qsize_t number)
+{
+ WARN_ON(dquot->dq_dqb.dqb_rsvspace < number);
+ dquot->dq_dqb.dqb_curspace += number;
+ dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
+static inline
+void dquot_free_reserved_space(struct dquot *dquot, qsize_t number)
+{
+ dquot->dq_dqb.dqb_rsvspace -= number;
+}
+
static inline void dquot_decr_inodes(struct dquot *dquot, qsize_t number)
{
if (sb_dqopt(dquot->dq_sb)->flags & DQUOT_NEGATIVE_USAGE ||
@@ -1452,6 +1469,72 @@ warn_put_all:
return ret;
}
+int dquot_claim_space(struct inode *inode, qsize_t number)
+{
+ int cnt;
+ int ret = QUOTA_OK;
+
+ if (IS_NOQUOTA(inode)) {
+ inode_add_bytes(inode, number);
+ goto out;
+ }
+
+ down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode)) {
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ inode_add_bytes(inode, number);
+ goto out;
+ }
+
+ spin_lock(&dq_data_lock);
+ /* Claim reserved quotas to allocated quotas */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (inode->i_dquot[cnt] != NODQUOT)
+ dquot_claim_reserved_space(inode->i_dquot[cnt],
+ number);
+ }
+ /* Update inode bytes */
+ inode_add_bytes(inode, number);
+ spin_unlock(&dq_data_lock);
+ /* Dirtify all the dquots - this can block when journalling */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++)
+ if (inode->i_dquot[cnt])
+ mark_dquot_dirty(inode->i_dquot[cnt]);
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+ return ret;
+}
+EXPORT_SYMBOL(dquot_claim_space);
+
+/*
+ * Release reserved quota space
+ */
+void dquot_release_reserved_space(struct inode *inode, qsize_t number)
+{
+ int cnt;
+
+ if (IS_NOQUOTA(inode))
+ goto out;
+
+ down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+ if (IS_NOQUOTA(inode))
+ goto out_unlock;
+
+ spin_lock(&dq_data_lock);
+ /* Release reserved dquots */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ if (inode->i_dquot[cnt] != NODQUOT)
+ dquot_free_reserved_space(inode->i_dquot[cnt], number);
+ }
+ spin_unlock(&dq_data_lock);
+
+out_unlock:
+ up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
+out:
+ return;
+}
+EXPORT_SYMBOL(dquot_release_reserved_space);
+
/*
* This operation can block, but only after everything is updated
*/
@@ -1529,6 +1612,19 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
}
/*
+ * call back function, get reserved quota space from underlying fs
+ */
+qsize_t dquot_get_reserved_space(struct inode *inode)
+{
+ qsize_t reserved_space = 0;
+
+ if (sb_any_quota_active(inode->i_sb) &&
+ inode->i_sb->dq_op->get_reserved_space)
+ reserved_space = inode->i_sb->dq_op->get_reserved_space(inode);
+ return reserved_space;
+}
+
+/*
* Transfer the number of inode and blocks from one diskquota to an other.
*
* This operation can block, but only after everything is updated
@@ -1536,7 +1632,8 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
*/
int dquot_transfer(struct inode *inode, struct iattr *iattr)
{
- qsize_t space;
+ qsize_t space, cur_space;
+ qsize_t rsv_space = 0;
struct dquot *transfer_from[MAXQUOTAS];
struct dquot *transfer_to[MAXQUOTAS];
int cnt, ret = QUOTA_OK;
@@ -1575,7 +1672,9 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
goto put_all;
}
spin_lock(&dq_data_lock);
- space = inode_get_bytes(inode);
+ cur_space = inode_get_bytes(inode);
+ rsv_space = dquot_get_reserved_space(inode);
+ space = cur_space + rsv_space;
/* Build the transfer_from list and check the limits */
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (transfer_to[cnt] == NODQUOT)
@@ -1604,11 +1703,14 @@ int dquot_transfer(struct inode *inode, struct iattr *iattr)
warntype_from_space[cnt] =
info_bdq_free(transfer_from[cnt], space);
dquot_decr_inodes(transfer_from[cnt], 1);
- dquot_decr_space(transfer_from[cnt], space);
+ dquot_decr_space(transfer_from[cnt], cur_space);
+ dquot_free_reserved_space(transfer_from[cnt],
+ rsv_space);
}
dquot_incr_inodes(transfer_to[cnt], 1);
- dquot_incr_space(transfer_to[cnt], space);
+ dquot_incr_space(transfer_to[cnt], cur_space);
+ dquot_resv_space(transfer_to[cnt], rsv_space);
inode->i_dquot[cnt] = transfer_to[cnt];
}
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 54b837f..a510d91 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -311,6 +311,12 @@ struct dquot_operations {
int (*write_info) (struct super_block *, int); /* Write of quota "superblock" */
/* reserve quota for delayed block allocation */
int (*reserve_space) (struct inode *, qsize_t, int);
+ /* claim reserved quota for delayed alloc */
+ int (*claim_space) (struct inode *, qsize_t);
+ /* release rsved quota for delayed alloc */
+ void (*release_rsv) (struct inode *, qsize_t);
+ /* get reserved quota for delayed alloc */
+ qsize_t (*get_reserved_space) (struct inode *);
};
/* Operations handling requests from userspace */
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 3e3a0d2..7369d04 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -35,6 +35,11 @@ void dquot_destroy(struct dquot *dquot);
int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
int dquot_alloc_inode(const struct inode *inode, qsize_t number);
+int dquot_reserve_space(struct inode *inode, qsize_t number, int prealloc);
+int dquot_claim_space(struct inode *inode, qsize_t number);
+void dquot_release_reserved_space(struct inode *inode, qsize_t number);
+qsize_t dquot_get_reserved_space(struct inode *inode);
+
int dquot_free_space(struct inode *inode, qsize_t number);
int dquot_free_inode(const struct inode *inode, qsize_t number);
@@ -203,6 +208,31 @@ static inline int vfs_dq_alloc_inode(struct inode *inode)
return 0;
}
+/*
+ * Convert in-memory reserved quotas to real consumed quotas
+ */
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+ if (sb_any_quota_active(inode->i_sb)) {
+ if (inode->i_sb->dq_op->claim_space(inode, nr) == NO_QUOTA)
+ return 1;
+ } else
+ inode_add_bytes(inode, nr);
+
+ mark_inode_dirty(inode);
+ return 0;
+}
+
+/*
+ * Release reserved (in-memory) quotas
+ */
+static inline
+void vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+ if (sb_any_quota_active(inode->i_sb))
+ inode->i_sb->dq_op->release_rsv(inode, nr);
+}
+
static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
{
if (sb_any_quota_active(inode->i_sb))
@@ -354,6 +384,17 @@ static inline int vfs_dq_reserve_space(struct inode *inode, qsize_t nr)
return 0;
}
+static inline int vfs_dq_claim_space(struct inode *inode, qsize_t nr)
+{
+ return vfs_dq_alloc_space(inode, nr);
+}
+
+static inline
+int vfs_dq_release_reservation_space(struct inode *inode, qsize_t nr)
+{
+ return 0;
+}
+
static inline void vfs_dq_free_space_nodirty(struct inode *inode, qsize_t nr)
{
inode_sub_bytes(inode, nr);
@@ -397,6 +438,18 @@ static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
nr << inode->i_blkbits);
}
+static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
+{
+ return vfs_dq_claim_space(inode,
+ nr << inode->i_blkbits);
+}
+
+static inline
+void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
+{
+ vfs_dq_release_reservation_space(inode, nr << inode->i_blkbits);
+}
+
static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
{
vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 07/11] quota: Use inode->i_blkbits to get block bits
2009-01-16 18:08 ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara
From: Mingming Cao <cmm@us.ibm.com>
Andrew has suggested to use inode->i_blkbits to get the block bits info,
rather than use super block's blockbits. That should be faster and emit
less code.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
include/linux/quotaops.h | 22 ++++++++--------------
1 files changed, 8 insertions(+), 14 deletions(-)
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 7369d04..69b502e 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -410,38 +410,32 @@ static inline void vfs_dq_free_space(struct inode *inode, qsize_t nr)
static inline int vfs_dq_prealloc_block_nodirty(struct inode *inode, qsize_t nr)
{
- return vfs_dq_prealloc_space_nodirty(inode,
- nr << inode->i_sb->s_blocksize_bits);
+ return vfs_dq_prealloc_space_nodirty(inode, nr << inode->i_blkbits);
}
static inline int vfs_dq_prealloc_block(struct inode *inode, qsize_t nr)
{
- return vfs_dq_prealloc_space(inode,
- nr << inode->i_sb->s_blocksize_bits);
+ return vfs_dq_prealloc_space(inode, nr << inode->i_blkbits);
}
static inline int vfs_dq_alloc_block_nodirty(struct inode *inode, qsize_t nr)
{
- return vfs_dq_alloc_space_nodirty(inode,
- nr << inode->i_sb->s_blocksize_bits);
+ return vfs_dq_alloc_space_nodirty(inode, nr << inode->i_blkbits);
}
static inline int vfs_dq_alloc_block(struct inode *inode, qsize_t nr)
{
- return vfs_dq_alloc_space(inode,
- nr << inode->i_sb->s_blocksize_bits);
+ return vfs_dq_alloc_space(inode, nr << inode->i_blkbits);
}
static inline int vfs_dq_reserve_block(struct inode *inode, qsize_t nr)
{
- return vfs_dq_reserve_space(inode,
- nr << inode->i_blkbits);
+ return vfs_dq_reserve_space(inode, nr << inode->i_blkbits);
}
static inline int vfs_dq_claim_block(struct inode *inode, qsize_t nr)
{
- return vfs_dq_claim_space(inode,
- nr << inode->i_blkbits);
+ return vfs_dq_claim_space(inode, nr << inode->i_blkbits);
}
static inline
@@ -452,12 +446,12 @@ void vfs_dq_release_reservation_block(struct inode *inode, qsize_t nr)
static inline void vfs_dq_free_block_nodirty(struct inode *inode, qsize_t nr)
{
- vfs_dq_free_space_nodirty(inode, nr << inode->i_sb->s_blocksize_bits);
+ vfs_dq_free_space_nodirty(inode, nr << inode->i_blkbits);
}
static inline void vfs_dq_free_block(struct inode *inode, qsize_t nr)
{
- vfs_dq_free_space(inode, nr << inode->i_sb->s_blocksize_bits);
+ vfs_dq_free_space(inode, nr << inode->i_blkbits);
}
/*
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles
2009-01-16 18:08 ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
0 siblings, 1 reply; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Mingming Cao, Jan Kara
From: Mingming Cao <cmm@us.ibm.com>
According to checkpatch: EXPORT_SYMBOL(foo); should immediately follow its
function/variable
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/dquot.c | 69 ++++++++++++++++++++++++++++-------------------------------
1 files changed, 33 insertions(+), 36 deletions(-)
diff --git a/fs/dquot.c b/fs/dquot.c
index 2916f91..28aa146 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -132,6 +132,7 @@
static DEFINE_SPINLOCK(dq_list_lock);
static DEFINE_SPINLOCK(dq_state_lock);
DEFINE_SPINLOCK(dq_data_lock);
+EXPORT_SYMBOL(dq_data_lock);
static char *quotatypes[] = INITQFNAMES;
static struct quota_format_type *quota_formats; /* List of registered formats */
@@ -148,6 +149,7 @@ int register_quota_format(struct quota_format_type *fmt)
spin_unlock(&dq_list_lock);
return 0;
}
+EXPORT_SYMBOL(register_quota_format);
void unregister_quota_format(struct quota_format_type *fmt)
{
@@ -159,6 +161,7 @@ void unregister_quota_format(struct quota_format_type *fmt)
*actqf = (*actqf)->qf_next;
spin_unlock(&dq_list_lock);
}
+EXPORT_SYMBOL(unregister_quota_format);
static struct quota_format_type *find_quota_format(int id)
{
@@ -215,6 +218,7 @@ static unsigned int dq_hash_bits, dq_hash_mask;
static struct hlist_head *dquot_hash;
struct dqstats dqstats;
+EXPORT_SYMBOL(dqstats);
static inline unsigned int
hashfn(const struct super_block *sb, unsigned int id, int type)
@@ -309,6 +313,7 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
spin_unlock(&dq_list_lock);
return 0;
}
+EXPORT_SYMBOL(dquot_mark_dquot_dirty);
/* This function needs dq_list_lock */
static inline int clear_dquot_dirty(struct dquot *dquot)
@@ -360,6 +365,7 @@ out_iolock:
mutex_unlock(&dquot->dq_lock);
return ret;
}
+EXPORT_SYMBOL(dquot_acquire);
/*
* Write dquot to disk
@@ -389,6 +395,7 @@ out_sem:
mutex_unlock(&dqopt->dqio_mutex);
return ret;
}
+EXPORT_SYMBOL(dquot_commit);
/*
* Release dquot
@@ -417,6 +424,7 @@ out_dqlock:
mutex_unlock(&dquot->dq_lock);
return ret;
}
+EXPORT_SYMBOL(dquot_release);
void dquot_destroy(struct dquot *dquot)
{
@@ -516,6 +524,7 @@ out:
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
return ret;
}
+EXPORT_SYMBOL(dquot_scan_active);
int vfs_quota_sync(struct super_block *sb, int type)
{
@@ -563,6 +572,7 @@ int vfs_quota_sync(struct super_block *sb, int type)
return 0;
}
+EXPORT_SYMBOL(vfs_quota_sync);
/* Free unused dquots from cache */
static void prune_dqcache(int count)
@@ -672,6 +682,7 @@ we_slept:
put_dquot_last(dquot);
spin_unlock(&dq_list_lock);
}
+EXPORT_SYMBOL(dqput);
struct dquot *dquot_alloc(struct super_block *sb, int type)
{
@@ -767,6 +778,7 @@ out:
return dquot;
}
+EXPORT_SYMBOL(dqget);
static int dqinit_needed(struct inode *inode, int type)
{
@@ -1282,6 +1294,7 @@ out_err:
dqput(got[cnt]);
return ret;
}
+EXPORT_SYMBOL(dquot_initialize);
/*
* Release all quotas referenced by inode
@@ -1302,6 +1315,7 @@ int dquot_drop(struct inode *inode)
dqput(put[cnt]);
return 0;
}
+EXPORT_SYMBOL(dquot_drop);
/* Wrapper to remove references to quota structures from inode */
void vfs_dq_drop(struct inode *inode)
@@ -1324,6 +1338,7 @@ void vfs_dq_drop(struct inode *inode)
inode->i_sb->dq_op->drop(inode);
}
}
+EXPORT_SYMBOL(vfs_dq_drop);
/*
* Following four functions update i_blocks+i_bytes fields and
@@ -1404,6 +1419,7 @@ out_unlock:
out:
return ret;
}
+EXPORT_SYMBOL(dquot_alloc_space);
int dquot_reserve_space(struct inode *inode, qsize_t number, int warn)
{
@@ -1468,6 +1484,7 @@ warn_put_all:
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return ret;
}
+EXPORT_SYMBOL(dquot_alloc_inode);
int dquot_claim_space(struct inode *inode, qsize_t number)
{
@@ -1574,6 +1591,7 @@ out_sub:
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return QUOTA_OK;
}
+EXPORT_SYMBOL(dquot_free_space);
/*
* This operation can block, but only after everything is updated
@@ -1610,6 +1628,7 @@ int dquot_free_inode(const struct inode *inode, qsize_t number)
up_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
return QUOTA_OK;
}
+EXPORT_SYMBOL(dquot_free_inode);
/*
* call back function, get reserved quota space from underlying fs
@@ -1746,6 +1765,7 @@ over_quota:
ret = NO_QUOTA;
goto warn_put_all;
}
+EXPORT_SYMBOL(dquot_transfer);
/* Wrapper for transferring ownership of an inode */
int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
@@ -1757,7 +1777,7 @@ int vfs_dq_transfer(struct inode *inode, struct iattr *iattr)
}
return 0;
}
-
+EXPORT_SYMBOL(vfs_dq_transfer);
/*
* Write info of quota file to disk
@@ -1772,6 +1792,7 @@ int dquot_commit_info(struct super_block *sb, int type)
mutex_unlock(&dqopt->dqio_mutex);
return ret;
}
+EXPORT_SYMBOL(dquot_commit_info);
/*
* Definitions of diskquota operations.
@@ -1924,13 +1945,14 @@ put_inodes:
}
return ret;
}
+EXPORT_SYMBOL(vfs_quota_disable);
int vfs_quota_off(struct super_block *sb, int type, int remount)
{
return vfs_quota_disable(sb, type, remount ? DQUOT_SUSPENDED :
(DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED));
}
-
+EXPORT_SYMBOL(vfs_quota_off);
/*
* Turn quotas on on a device
*/
@@ -2087,6 +2109,7 @@ int vfs_quota_on_path(struct super_block *sb, int type, int format_id,
DQUOT_LIMITS_ENABLED);
return error;
}
+EXPORT_SYMBOL(vfs_quota_on_path);
int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
int remount)
@@ -2104,6 +2127,7 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *name,
}
return error;
}
+EXPORT_SYMBOL(vfs_quota_on);
/*
* More powerful function for turning on quotas allowing setting
@@ -2150,6 +2174,7 @@ out_lock:
load_quota:
return vfs_load_quota_inode(inode, type, format_id, flags);
}
+EXPORT_SYMBOL(vfs_quota_enable);
/*
* This function is used when filesystem needs to initialize quotas
@@ -2179,6 +2204,7 @@ out:
dput(dentry);
return error;
}
+EXPORT_SYMBOL(vfs_quota_on_mount);
/* Wrapper to turn on quotas when remounting rw */
int vfs_dq_quota_on_remount(struct super_block *sb)
@@ -2195,6 +2221,7 @@ int vfs_dq_quota_on_remount(struct super_block *sb)
}
return ret;
}
+EXPORT_SYMBOL(vfs_dq_quota_on_remount);
static inline qsize_t qbtos(qsize_t blocks)
{
@@ -2236,6 +2263,7 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
return 0;
}
+EXPORT_SYMBOL(vfs_get_dqblk);
/* Generic routine for setting common part of quota structure */
static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di)
@@ -2327,6 +2355,7 @@ int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d
out:
return rc;
}
+EXPORT_SYMBOL(vfs_set_dqblk);
/* Generic routine for getting common part of quota file information */
int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
@@ -2348,6 +2377,7 @@ int vfs_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
return 0;
}
+EXPORT_SYMBOL(vfs_get_dqinfo);
/* Generic routine for setting common part of quota file information */
int vfs_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii)
@@ -2376,6 +2406,7 @@ out:
mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
return err;
}
+EXPORT_SYMBOL(vfs_set_dqinfo);
struct quotactl_ops vfs_quotactl_ops = {
.quota_on = vfs_quota_on,
@@ -2531,37 +2562,3 @@ static int __init dquot_init(void)
return 0;
}
module_init(dquot_init);
-
-EXPORT_SYMBOL(register_quota_format);
-EXPORT_SYMBOL(unregister_quota_format);
-EXPORT_SYMBOL(dqstats);
-EXPORT_SYMBOL(dq_data_lock);
-EXPORT_SYMBOL(vfs_quota_enable);
-EXPORT_SYMBOL(vfs_quota_on);
-EXPORT_SYMBOL(vfs_quota_on_path);
-EXPORT_SYMBOL(vfs_quota_on_mount);
-EXPORT_SYMBOL(vfs_quota_disable);
-EXPORT_SYMBOL(vfs_quota_off);
-EXPORT_SYMBOL(dquot_scan_active);
-EXPORT_SYMBOL(vfs_quota_sync);
-EXPORT_SYMBOL(vfs_get_dqinfo);
-EXPORT_SYMBOL(vfs_set_dqinfo);
-EXPORT_SYMBOL(vfs_get_dqblk);
-EXPORT_SYMBOL(vfs_set_dqblk);
-EXPORT_SYMBOL(dquot_commit);
-EXPORT_SYMBOL(dquot_commit_info);
-EXPORT_SYMBOL(dquot_acquire);
-EXPORT_SYMBOL(dquot_release);
-EXPORT_SYMBOL(dquot_mark_dquot_dirty);
-EXPORT_SYMBOL(dquot_initialize);
-EXPORT_SYMBOL(dquot_drop);
-EXPORT_SYMBOL(vfs_dq_drop);
-EXPORT_SYMBOL(dqget);
-EXPORT_SYMBOL(dqput);
-EXPORT_SYMBOL(dquot_alloc_space);
-EXPORT_SYMBOL(dquot_alloc_inode);
-EXPORT_SYMBOL(dquot_free_space);
-EXPORT_SYMBOL(dquot_free_inode);
-EXPORT_SYMBOL(dquot_transfer);
-EXPORT_SYMBOL(vfs_dq_transfer);
-EXPORT_SYMBOL(vfs_dq_quota_on_remount);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 09/11] ext3: Remove unnecessary quota functions
2009-01-16 18:08 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 10/11] ext4: " Jan Kara
2009-01-20 21:41 ` [PATCH 09/11] ext3: " Mingming Cao
0 siblings, 2 replies; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
ext3_dquot_initialize() and ext3_dquot_drop() is no longer
needed because of modified quota locking.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext3/super.c | 44 ++------------------------------------------
1 files changed, 2 insertions(+), 42 deletions(-)
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index b70d90e..ec410a9 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -707,8 +707,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
#define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
-static int ext3_dquot_initialize(struct inode *inode, int type);
-static int ext3_dquot_drop(struct inode *inode);
static int ext3_write_dquot(struct dquot *dquot);
static int ext3_acquire_dquot(struct dquot *dquot);
static int ext3_release_dquot(struct dquot *dquot);
@@ -723,8 +721,8 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
static struct dquot_operations ext3_quota_operations = {
- .initialize = ext3_dquot_initialize,
- .drop = ext3_dquot_drop,
+ .initialize = dquot_initialize,
+ .drop = dquot_drop,
.alloc_space = dquot_alloc_space,
.alloc_inode = dquot_alloc_inode,
.free_space = dquot_free_space,
@@ -2713,44 +2711,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
}
-static int ext3_dquot_initialize(struct inode *inode, int type)
-{
- handle_t *handle;
- int ret, err;
-
- /* We may create quota structure so we need to reserve enough blocks */
- handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
- if (IS_ERR(handle))
- return PTR_ERR(handle);
- ret = dquot_initialize(inode, type);
- err = ext3_journal_stop(handle);
- if (!ret)
- ret = err;
- return ret;
-}
-
-static int ext3_dquot_drop(struct inode *inode)
-{
- handle_t *handle;
- int ret, err;
-
- /* We may delete quota structure so we need to reserve enough blocks */
- handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
- if (IS_ERR(handle)) {
- /*
- * We call dquot_drop() anyway to at least release references
- * to quota structures so that umount does not hang.
- */
- dquot_drop(inode);
- return PTR_ERR(handle);
- }
- ret = dquot_drop(inode);
- err = ext3_journal_stop(handle);
- if (!ret)
- ret = err;
- return ret;
-}
-
static int ext3_write_dquot(struct dquot *dquot)
{
int ret, err;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 10/11] ext4: Remove unnecessary quota functions
2009-01-16 18:08 ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-16 18:08 ` [PATCH 11/11] reiserfs: " Jan Kara
2009-01-20 21:41 ` [PATCH 10/11] ext4: " Mingming Cao
2009-01-20 21:41 ` [PATCH 09/11] ext3: " Mingming Cao
1 sibling, 2 replies; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
ext4_dquot_initialize() and ext4_dquot_drop() is no longer
needed because of modified quota locking.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext4/super.c | 44 ++------------------------------------------
1 files changed, 2 insertions(+), 42 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e5f06a5..f0785fd 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -926,8 +926,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_
#define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
#define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
-static int ext4_dquot_initialize(struct inode *inode, int type);
-static int ext4_dquot_drop(struct inode *inode);
static int ext4_write_dquot(struct dquot *dquot);
static int ext4_acquire_dquot(struct dquot *dquot);
static int ext4_release_dquot(struct dquot *dquot);
@@ -942,8 +940,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
const char *data, size_t len, loff_t off);
static struct dquot_operations ext4_quota_operations = {
- .initialize = ext4_dquot_initialize,
- .drop = ext4_dquot_drop,
+ .initialize = dquot_initialize,
+ .drop = dquot_drop,
.alloc_space = dquot_alloc_space,
.alloc_inode = dquot_alloc_inode,
.free_space = dquot_free_space,
@@ -3378,44 +3376,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
}
-static int ext4_dquot_initialize(struct inode *inode, int type)
-{
- handle_t *handle;
- int ret, err;
-
- /* We may create quota structure so we need to reserve enough blocks */
- handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb));
- if (IS_ERR(handle))
- return PTR_ERR(handle);
- ret = dquot_initialize(inode, type);
- err = ext4_journal_stop(handle);
- if (!ret)
- ret = err;
- return ret;
-}
-
-static int ext4_dquot_drop(struct inode *inode)
-{
- handle_t *handle;
- int ret, err;
-
- /* We may delete quota structure so we need to reserve enough blocks */
- handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
- if (IS_ERR(handle)) {
- /*
- * We call dquot_drop() anyway to at least release references
- * to quota structures so that umount does not hang.
- */
- dquot_drop(inode);
- return PTR_ERR(handle);
- }
- ret = dquot_drop(inode);
- err = ext4_journal_stop(handle);
- if (!ret)
- ret = err;
- return ret;
-}
-
static int ext4_write_dquot(struct dquot *dquot)
{
int ret, err;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 11/11] reiserfs: Remove unnecessary quota functions
2009-01-16 18:08 ` [PATCH 10/11] ext4: " Jan Kara
@ 2009-01-16 18:08 ` Jan Kara
2009-01-20 21:41 ` [PATCH 10/11] ext4: " Mingming Cao
1 sibling, 0 replies; 56+ messages in thread
From: Jan Kara @ 2009-01-16 18:08 UTC (permalink / raw)
To: linux-kernel; +Cc: linux-ext4, linux-fsdevel, Jan Kara
reiserfs_dquot_initialize() and reiserfs_dquot_drop() is no longer
needed because of modified quota locking.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/reiserfs/super.c | 58 +-------------------------------------------------
1 files changed, 2 insertions(+), 56 deletions(-)
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index f3c820b..317c035 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -629,8 +629,6 @@ static const struct super_operations reiserfs_sops = {
#ifdef CONFIG_QUOTA
#define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
-static int reiserfs_dquot_initialize(struct inode *, int);
-static int reiserfs_dquot_drop(struct inode *);
static int reiserfs_write_dquot(struct dquot *);
static int reiserfs_acquire_dquot(struct dquot *);
static int reiserfs_release_dquot(struct dquot *);
@@ -639,8 +637,8 @@ static int reiserfs_write_info(struct super_block *, int);
static int reiserfs_quota_on(struct super_block *, int, int, char *, int);
static struct dquot_operations reiserfs_quota_operations = {
- .initialize = reiserfs_dquot_initialize,
- .drop = reiserfs_dquot_drop,
+ .initialize = dquot_initialize,
+ .drop = dquot_drop,
.alloc_space = dquot_alloc_space,
.alloc_inode = dquot_alloc_inode,
.free_space = dquot_free_space,
@@ -1896,58 +1894,6 @@ static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf)
}
#ifdef CONFIG_QUOTA
-static int reiserfs_dquot_initialize(struct inode *inode, int type)
-{
- struct reiserfs_transaction_handle th;
- int ret, err;
-
- /* We may create quota structure so we need to reserve enough blocks */
- reiserfs_write_lock(inode->i_sb);
- ret =
- journal_begin(&th, inode->i_sb,
- 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
- if (ret)
- goto out;
- ret = dquot_initialize(inode, type);
- err =
- journal_end(&th, inode->i_sb,
- 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
- if (!ret && err)
- ret = err;
- out:
- reiserfs_write_unlock(inode->i_sb);
- return ret;
-}
-
-static int reiserfs_dquot_drop(struct inode *inode)
-{
- struct reiserfs_transaction_handle th;
- int ret, err;
-
- /* We may delete quota structure so we need to reserve enough blocks */
- reiserfs_write_lock(inode->i_sb);
- ret =
- journal_begin(&th, inode->i_sb,
- 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
- if (ret) {
- /*
- * We call dquot_drop() anyway to at least release references
- * to quota structures so that umount does not hang.
- */
- dquot_drop(inode);
- goto out;
- }
- ret = dquot_drop(inode);
- err =
- journal_end(&th, inode->i_sb,
- 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
- if (!ret && err)
- ret = err;
- out:
- reiserfs_write_unlock(inode->i_sb);
- return ret;
-}
^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH 09/11] ext3: Remove unnecessary quota functions
2009-01-16 18:08 ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
2009-01-16 18:08 ` [PATCH 10/11] ext4: " Jan Kara
@ 2009-01-20 21:41 ` Mingming Cao
1 sibling, 0 replies; 56+ messages in thread
From: Mingming Cao @ 2009-01-20 21:41 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel
在 2009-01-16五的 19:08 +0100,Jan Kara写道:
> ext3_dquot_initialize() and ext3_dquot_drop() is no longer
> needed because of modified quota locking.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed_by: Mingming Cao <cmm@us.ibm.com>
> ---
> fs/ext3/super.c | 44 ++------------------------------------------
> 1 files changed, 2 insertions(+), 42 deletions(-)
>
> diff --git a/fs/ext3/super.c b/fs/ext3/super.c
> index b70d90e..ec410a9 100644
> --- a/fs/ext3/super.c
> +++ b/fs/ext3/super.c
> @@ -707,8 +707,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page,
> #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group")
> #define QTYPE2MOPT(on, t) ((t)==USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
>
> -static int ext3_dquot_initialize(struct inode *inode, int type);
> -static int ext3_dquot_drop(struct inode *inode);
> static int ext3_write_dquot(struct dquot *dquot);
> static int ext3_acquire_dquot(struct dquot *dquot);
> static int ext3_release_dquot(struct dquot *dquot);
> @@ -723,8 +721,8 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
> const char *data, size_t len, loff_t off);
>
> static struct dquot_operations ext3_quota_operations = {
> - .initialize = ext3_dquot_initialize,
> - .drop = ext3_dquot_drop,
> + .initialize = dquot_initialize,
> + .drop = dquot_drop,
> .alloc_space = dquot_alloc_space,
> .alloc_inode = dquot_alloc_inode,
> .free_space = dquot_free_space,
> @@ -2713,44 +2711,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
> return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
> }
>
> -static int ext3_dquot_initialize(struct inode *inode, int type)
> -{
> - handle_t *handle;
> - int ret, err;
> -
> - /* We may create quota structure so we need to reserve enough blocks */
> - handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
> - if (IS_ERR(handle))
> - return PTR_ERR(handle);
> - ret = dquot_initialize(inode, type);
> - err = ext3_journal_stop(handle);
> - if (!ret)
> - ret = err;
> - return ret;
> -}
> -
> -static int ext3_dquot_drop(struct inode *inode)
> -{
> - handle_t *handle;
> - int ret, err;
> -
> - /* We may delete quota structure so we need to reserve enough blocks */
> - handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
> - if (IS_ERR(handle)) {
> - /*
> - * We call dquot_drop() anyway to at least release references
> - * to quota structures so that umount does not hang.
> - */
> - dquot_drop(inode);
> - return PTR_ERR(handle);
> - }
> - ret = dquot_drop(inode);
> - err = ext3_journal_stop(handle);
> - if (!ret)
> - ret = err;
> - return ret;
> -}
> -
> static int ext3_write_dquot(struct dquot *dquot)
> {
> int ret, err;
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 10/11] ext4: Remove unnecessary quota functions
2009-01-16 18:08 ` [PATCH 10/11] ext4: " Jan Kara
2009-01-16 18:08 ` [PATCH 11/11] reiserfs: " Jan Kara
@ 2009-01-20 21:41 ` Mingming Cao
1 sibling, 0 replies; 56+ messages in thread
From: Mingming Cao @ 2009-01-20 21:41 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel
在 2009-01-16五的 19:08 +0100,Jan Kara写道:
> ext4_dquot_initialize() and ext4_dquot_drop() is no longer
> needed because of modified quota locking.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed_by: Mingming Cao <cmm@us.ibm.com>
> ---
> fs/ext4/super.c | 44 ++------------------------------------------
> 1 files changed, 2 insertions(+), 42 deletions(-)
>
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index e5f06a5..f0785fd 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -926,8 +926,6 @@ static int bdev_try_to_free_page(struct super_block *sb, struct page *page, gfp_
> #define QTYPE2NAME(t) ((t) == USRQUOTA ? "user" : "group")
> #define QTYPE2MOPT(on, t) ((t) == USRQUOTA?((on)##USRJQUOTA):((on)##GRPJQUOTA))
>
> -static int ext4_dquot_initialize(struct inode *inode, int type);
> -static int ext4_dquot_drop(struct inode *inode);
> static int ext4_write_dquot(struct dquot *dquot);
> static int ext4_acquire_dquot(struct dquot *dquot);
> static int ext4_release_dquot(struct dquot *dquot);
> @@ -942,8 +940,8 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
> const char *data, size_t len, loff_t off);
>
> static struct dquot_operations ext4_quota_operations = {
> - .initialize = ext4_dquot_initialize,
> - .drop = ext4_dquot_drop,
> + .initialize = dquot_initialize,
> + .drop = dquot_drop,
> .alloc_space = dquot_alloc_space,
> .alloc_inode = dquot_alloc_inode,
> .free_space = dquot_free_space,
> @@ -3378,44 +3376,6 @@ static inline struct inode *dquot_to_inode(struct dquot *dquot)
> return sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
> }
>
> -static int ext4_dquot_initialize(struct inode *inode, int type)
> -{
> - handle_t *handle;
> - int ret, err;
> -
> - /* We may create quota structure so we need to reserve enough blocks */
> - handle = ext4_journal_start(inode, 2*EXT4_QUOTA_INIT_BLOCKS(inode->i_sb));
> - if (IS_ERR(handle))
> - return PTR_ERR(handle);
> - ret = dquot_initialize(inode, type);
> - err = ext4_journal_stop(handle);
> - if (!ret)
> - ret = err;
> - return ret;
> -}
> -
> -static int ext4_dquot_drop(struct inode *inode)
> -{
> - handle_t *handle;
> - int ret, err;
> -
> - /* We may delete quota structure so we need to reserve enough blocks */
> - handle = ext4_journal_start(inode, 2*EXT4_QUOTA_DEL_BLOCKS(inode->i_sb));
> - if (IS_ERR(handle)) {
> - /*
> - * We call dquot_drop() anyway to at least release references
> - * to quota structures so that umount does not hang.
> - */
> - dquot_drop(inode);
> - return PTR_ERR(handle);
> - }
> - ret = dquot_drop(inode);
> - err = ext4_journal_stop(handle);
> - if (!ret)
> - ret = err;
> - return ret;
> -}
> -
> static int ext4_write_dquot(struct dquot *dquot)
> {
> int ret, err;
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 01/11] quota: Improve locking
2009-01-16 18:08 ` [PATCH 01/11] quota: Improve locking Jan Kara
2009-01-16 18:08 ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
@ 2009-01-24 7:49 ` Andrew Morton
2009-01-26 10:04 ` Jan Kara
1 sibling, 1 reply; 56+ messages in thread
From: Andrew Morton @ 2009-01-24 7:49 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-kernel, linux-ext4, linux-fsdevel
On Fri, 16 Jan 2009 19:08:09 +0100 Jan Kara <jack@suse.cz> wrote:
> static DEFINE_SPINLOCK(dq_list_lock);
> +static DEFINE_SPINLOCK(dq_state_lock);
> DEFINE_SPINLOCK(dq_data_lock);
The chances are very good that two or even three of these locks will
all get placed into the same cacheline in main memory. The effects
will be quite bad if different CPUs (or, worse, different nodes) are
taking these locks.
For single, kernel-wide locks like these I think we should almost
always pad out to a cacheline.
With __cacheline_aligned_in_smp, rather than __cacheline_aligned.
Because spinlocks do take space even in uniprocessor builds.
There are probably lots of existing locks which should be converted.
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 01/11] quota: Improve locking
2009-01-24 7:49 ` [PATCH 01/11] quota: Improve locking Andrew Morton
@ 2009-01-26 10:04 ` Jan Kara
0 siblings, 0 replies; 56+ messages in thread
From: Jan Kara @ 2009-01-26 10:04 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, linux-ext4, linux-fsdevel
On Fri 23-01-09 23:49:12, Andrew Morton wrote:
> On Fri, 16 Jan 2009 19:08:09 +0100 Jan Kara <jack@suse.cz> wrote:
>
> > static DEFINE_SPINLOCK(dq_list_lock);
> > +static DEFINE_SPINLOCK(dq_state_lock);
> > DEFINE_SPINLOCK(dq_data_lock);
>
> The chances are very good that two or even three of these locks will
> all get placed into the same cacheline in main memory. The effects
> will be quite bad if different CPUs (or, worse, different nodes) are
> taking these locks.
>
> For single, kernel-wide locks like these I think we should almost
> always pad out to a cacheline.
I never thought about this. Thanks for the idea.
> With __cacheline_aligned_in_smp, rather than __cacheline_aligned.
> Because spinlocks do take space even in uniprocessor builds.
I've added this to my list of quota cleanups.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 56+ messages in thread
* [RFC][PATCH 00/10] cifs: local caching support using FS-Cache
[not found] <yes>
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
@ 2010-06-22 15:20 ` Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
` (17 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:20 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
This patchset is a first stab at adding persistent, local caching facility for
CIFS using the FS-Cache interface.
The index hierarchy which is mainly used to locate a file object or discard
a certain subset of the files cached, currently has three levels:
- Server
- Share
- File
The server index object is keyed by hostname of the server. The superblock
index object is keyed by the sharename and the inode object is keyed by the
UniqueId. The cache coherency is ensured by checking the 'LastWriteTime' and
size of file.
To use this, apply this patchset in order, mount the share with rsize=4096 and
try copying a huge file (say few hundred MBs) from mount point to local
filesystem. During the first time, the cache will be initialized. When you copy
the second time, it should read from the local cache.
To reduce the impact of page cache and see the local caching in action
readily, try doing a sync and drop the caches by doing:
sync; echo 3 > /proc/sys/vm/drop_caches
Known issues
-------------
- the cache coherency check may not be reliable always as some
CIFS servers are known not to update mtime until the filehandle is
closed.
- not all the Servers under all circumstances provide a unique
'UniqueId'.
Todo's
-------
- improvements to avoid potential key collisions
- address the above known issues
This set is lightly tested and all the bugs seen during my testing have been
fixed. However, this can be considered as an RFC for now.
Any Comments or Suggestions are welcome.
Suresh Jayaraman (10)
cifs: add kernel config option for CIFS Client caching support
cifs: guard cifsglob.h against multiple inclusion
cifs: register CIFS for caching
cifs: define server-level cache index objects and register them with FS-Cache
cifs: define superblock-level cache index objects and register them
cifs: define inode-level cache object and register them
cifs: FS-Cache page management
cifs: store pages into local cache
cifs: read pages from FS-Cache
cifs: add mount option to enable local caching
Kconfig | 9 ++
Makefile | 2
cache.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cifs_fs_sb.h | 1
cifsfs.c | 15 +++
cifsglob.h | 14 +++
connect.c | 16 +++
file.c | 51 +++++++++++
fscache.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
fscache.h | 135 +++++++++++++++++++++++++++++++
inode.c | 4
11 files changed, 742 insertions(+)
^ permalink raw reply [flat|nested] 56+ messages in thread
* [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support
[not found] <yes>
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
@ 2010-06-22 15:22 ` Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
` (16 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:22 UTC (permalink / raw)
To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells
Add a kernel config option to enable local caching for CIFS.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
fs/cifs/Kconfig | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
index 80f3525..5739fd7 100644
--- a/fs/cifs/Kconfig
+++ b/fs/cifs/Kconfig
@@ -131,6 +131,15 @@ config CIFS_DFS_UPCALL
IP addresses) which is needed for implicit mounts of DFS junction
points. If unsure, say N.
+config CIFS_FSCACHE
+ bool "Provide CIFS client caching support (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y
+ help
+ Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data
+ to be cached locally on disk through the general filesystem cache
+ manager. If unsure, say N.
+
config CIFS_EXPERIMENTAL
bool "CIFS Experimental Features (EXPERIMENTAL)"
depends on CIFS && EXPERIMENTAL
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion
[not found] <yes>
` (2 preceding siblings ...)
2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
@ 2010-06-22 15:22 ` Suresh Jayaraman
[not found] ` <1277220170-3442-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
` (15 subsequent siblings)
19 siblings, 1 reply; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:22 UTC (permalink / raw)
To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells
Add conditional compile macros to guard the header file against multiple
inclusion.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
fs/cifs/cifsglob.h | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index a88479c..6b2c39d 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -16,6 +16,9 @@
* the GNU Lesser General Public License for more details.
*
*/
+#ifndef _CIFS_GLOB_H
+#define _CIFS_GLOB_H
+
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/slab.h>
@@ -733,3 +736,5 @@ GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
extern const struct slow_work_ops cifs_oplock_break_ops;
+
+#endif /* _CIFS_GLOB_H */
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 03/10] cifs: register CIFS for caching
[not found] <yes>
` (3 preceding siblings ...)
2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
` (14 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
Define CIFS for FS-Cache and register for caching. Upon registration the
top-level index object cookie will be stuck to the netfs definition by
FS-Cache.
Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
---
fs/cifs/Makefile | 2 ++
fs/cifs/cache.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/cifsfs.c | 8 ++++++++
fs/cifs/fscache.h | 40 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 103 insertions(+), 0 deletions(-)
create mode 100644 fs/cifs/cache.c
create mode 100644 fs/cifs/fscache.h
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 9948c00..e2de709 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -11,3 +11,5 @@ cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \
cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
+
+cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
new file mode 100644
index 0000000..1080b96
--- /dev/null
+++ b/fs/cifs/cache.c
@@ -0,0 +1,53 @@
+/*
+ * fs/cifs/cache.c - CIFS filesystem cache index structure definitions
+ *
+ * Copyright (c) 2010 Novell, Inc.
+ * Authors(s): Suresh Jayaraman (sjayaraman-l3A5Bk7waGM@public.gmane.org>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+
+#include "fscache.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+/*
+ * CIFS filesystem definition for FS-Cache
+ */
+struct fscache_netfs cifs_fscache_netfs = {
+ .name = "cifs",
+ .version = 0,
+};
+
+/*
+ * Register CIFS for caching with FS-Cache
+ */
+int cifs_fscache_register(void)
+{
+ return fscache_register_netfs(&cifs_fscache_netfs);
+}
+
+/*
+ * Unregister CIFS for caching
+ */
+void cifs_fscache_unregister(void)
+{
+ fscache_unregister_netfs(&cifs_fscache_netfs);
+}
+
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 484e52b..c2a7aa9 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -47,6 +47,7 @@
#include <linux/key-type.h>
#include "dns_resolve.h"
#include "cifs_spnego.h"
+#include "fscache.h"
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
int cifsFYI = 0;
@@ -902,6 +903,10 @@ init_cifs(void)
cFYI(1, "cifs_max_pending set to max of 256");
}
+ rc = cifs_fscache_register();
+ if (rc)
+ goto out;
+
rc = cifs_init_inodecache();
if (rc)
goto out_clean_proc;
@@ -949,8 +954,10 @@ init_cifs(void)
cifs_destroy_mids();
out_destroy_inodecache:
cifs_destroy_inodecache();
+ cifs_fscache_unregister();
out_clean_proc:
cifs_proc_clean();
+ out:
return rc;
}
@@ -959,6 +966,7 @@ exit_cifs(void)
{
cFYI(DBG2, "exit_cifs");
cifs_proc_clean();
+ cifs_fscache_unregister();
#ifdef CONFIG_CIFS_DFS_UPCALL
cifs_dfs_release_automount_timer();
unregister_key_type(&key_type_dns_resolver);
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
new file mode 100644
index 0000000..cec9e2b
--- /dev/null
+++ b/fs/cifs/fscache.h
@@ -0,0 +1,40 @@
+/*
+ * fs/cifs/fscache.h - CIFS filesystem cache interface definitions
+ *
+ * Copyright (c) 2010 Novell, Inc.
+ * Authors(s): Suresh Jayaraman (sjayaraman-l3A5Bk7waGM@public.gmane.org>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef _CIFS_FSCACHE_H
+#define _CIFS_FSCACHE_H
+
+#include <linux/fscache.h>
+#include "cifsglob.h"
+
+#ifdef CONFIG_CIFS_FSCACHE
+
+extern struct fscache_netfs cifs_fscache_netfs;
+
+extern int cifs_fscache_register(void);
+extern void cifs_fscache_unregister(void);
+
+#else /* CONFIG_CIFS_FSCACHE */
+static inline int cifs_fscache_register(void) { return 0; }
+static inline void cifs_fscache_unregister(void) {}
+
+#endif /* CONFIG_CIFS_FSCACHE */
+
+#endif /* _CIFS_FSCACHE_H */
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
[not found] <yes>
` (4 preceding siblings ...)
2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
[not found] ` <1277220198-3522-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
` (13 subsequent siblings)
19 siblings, 1 reply; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
Define server-level cache index objects (as managed by TCP_ServerInfo structs).
Each server object is created in the CIFS top-level index object and is itself
an index into which superblock-level objects are inserted.
Currently, the server objects are keyed by hostname.
Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
---
fs/cifs/Makefile | 2 +-
fs/cifs/cache.c | 25 +++++++++++++++++++++++++
fs/cifs/cifsglob.h | 3 +++
fs/cifs/connect.c | 4 ++++
fs/cifs/fscache.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/fscache.h | 12 ++++++++++++
6 files changed, 92 insertions(+), 1 deletion(-)
create mode 100644 fs/cifs/fscache.c
Index: cifs-2.6/fs/cifs/Makefile
===================================================================
--- cifs-2.6.orig/fs/cifs/Makefile
+++ cifs-2.6/fs/cifs/Makefile
@@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
-cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
+cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
fscache_unregister_netfs(&cifs_fscache_netfs);
}
+/*
+ * Server object currently keyed by hostname
+ */
+static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
+ void *buffer, uint16_t maxbuf)
+{
+ const struct TCP_Server_Info *server = cookie_netfs_data;
+ uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
+
+ if (len > maxbuf)
+ return 0;
+
+ memcpy(buffer, server->hostname, len);
+
+ return len;
+}
+
+/*
+ * Server object for FS-Cache
+ */
+const struct fscache_cookie_def cifs_fscache_server_index_def = {
+ .name = "CIFS.server",
+ .type = FSCACHE_COOKIE_TYPE_INDEX,
+ .get_key = cifs_server_get_key,
+};
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -193,6 +193,9 @@ struct TCP_Server_Info {
bool sec_mskerberos; /* supports legacy MS Kerberos */
bool sec_kerberosu2u; /* supports U2U Kerberos */
bool sec_ntlmssp; /* supports NTLMSSP */
+#ifdef CONFIG_CIFS_FSCACHE
+ struct fscache_cookie *fscache; /* client index cache cookie */
+#endif
};
/*
Index: cifs-2.6/fs/cifs/connect.c
===================================================================
--- cifs-2.6.orig/fs/cifs/connect.c
+++ cifs-2.6/fs/cifs/connect.c
@@ -48,6 +48,7 @@
#include "nterr.h"
#include "rfc1002pdu.h"
#include "cn_cifs.h"
+#include "fscache.h"
#define CIFS_PORT 445
#define RFC1001_PORT 139
@@ -1453,6 +1454,8 @@ cifs_put_tcp_session(struct TCP_Server_I
return;
}
+ cifs_fscache_release_client_cookie(server);
+
list_del_init(&server->tcp_ses_list);
write_unlock(&cifs_tcp_ses_lock);
@@ -1572,6 +1575,7 @@ cifs_get_tcp_session(struct smb_vol *vol
goto out_err;
}
+ cifs_fscache_get_client_cookie(tcp_ses);
/* thread spawned, put it on the list */
write_lock(&cifs_tcp_ses_lock);
list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- /dev/null
+++ cifs-2.6/fs/cifs/fscache.c
@@ -0,0 +1,47 @@
+/*
+ * fs/cifs/fscache.c - CIFS filesystem cache interface
+ *
+ * Copyright (c) 2010 Novell, Inc.
+ * Authors(s): Suresh Jayaraman (sjayaraman-l3A5Bk7waGM@public.gmane.org>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/in6.h>
+
+#include "fscache.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+
+void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
+{
+ server->fscache =
+ fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
+ &cifs_fscache_server_index_def, server);
+ cFYI(1, "CIFS: get client cookie (0x%p/0x%p)\n",
+ server, server->fscache);
+}
+
+void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
+{
+ cFYI(1, "CIFS: release client cookie (0x%p/0x%p)\n",
+ server, server->fscache);
+ fscache_relinquish_cookie(server->fscache, 0);
+ server->fscache = NULL;
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -27,14 +27,26 @@
#ifdef CONFIG_CIFS_FSCACHE
extern struct fscache_netfs cifs_fscache_netfs;
+extern const struct fscache_cookie_def cifs_fscache_server_index_def;
extern int cifs_fscache_register(void);
extern void cifs_fscache_unregister(void);
+/*
+ * fscache.c
+ */
+extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
+extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
+
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
+static inline void
+cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
+static inline void
+cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
+
#endif /* CONFIG_CIFS_FSCACHE */
#endif /* _CIFS_FSCACHE_H */
^ permalink raw reply [flat|nested] 56+ messages in thread
* [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
[not found] <yes>
` (5 preceding siblings ...)
2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
` (12 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
Define superblock-level cache index objects (managed by cifsTconInfo structs).
Each superblock object is created in a server-level index object and in itself
an index into which inode-level objects are inserted.
Currently, the superblock objects are keyed by sharename.
Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
---
fs/cifs/cache.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/cifsglob.h | 3 ++
fs/cifs/connect.c | 4 +++
fs/cifs/fscache.c | 17 ++++++++++++++
fs/cifs/fscache.h | 6 +++++
5 files changed, 92 insertions(+)
Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -76,3 +76,65 @@ const struct fscache_cookie_def cifs_fsc
.type = FSCACHE_COOKIE_TYPE_INDEX,
.get_key = cifs_server_get_key,
};
+
+static char *extract_sharename(const char *treename)
+{
+ const char *src;
+ char *delim, *dst;
+ int len;
+
+ /* skip double chars at the beginning */
+ src = treename + 2;
+
+ /* share name is always preceded by '\\' now */
+ delim = strchr(src, '\\');
+ if (!delim)
+ return ERR_PTR(-EINVAL);
+ delim++;
+ len = strlen(delim);
+
+ /* caller has to free the memory */
+ dst = kstrndup(delim, len, GFP_KERNEL);
+ if (!dst)
+ return ERR_PTR(-ENOMEM);
+
+ return dst;
+}
+
+/*
+ * Superblock object currently keyed by share name
+ */
+static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
+ uint16_t maxbuf)
+{
+ const struct cifsTconInfo *tcon = cookie_netfs_data;
+ char *sharename;
+ uint16_t len;
+
+ sharename = extract_sharename(tcon->treeName);
+ if (IS_ERR(sharename)) {
+ cFYI(1, "CIFS: couldn't extract sharename\n");
+ sharename = NULL;
+ return 0;
+ }
+
+ len = strlen(sharename);
+ if (len > maxbuf)
+ return 0;
+
+ memcpy(buffer, sharename, len);
+
+ kfree(sharename);
+
+ return len;
+}
+
+/*
+ * Superblock object for FS-Cache
+ */
+const struct fscache_cookie_def cifs_fscache_super_index_def = {
+ .name = "CIFS.super",
+ .type = FSCACHE_COOKIE_TYPE_INDEX,
+ .get_key = cifs_super_get_key,
+};
+
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -317,6 +317,9 @@ struct cifsTconInfo {
bool local_lease:1; /* check leases (only) on local system not remote */
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
bool need_reconnect:1; /* connection reset, tid now invalid */
+#ifdef CONFIG_CIFS_FSCACHE
+ struct fscache_cookie *fscache; /* cookie for share */
+#endif
/* BB add field for back pointer to sb struct(s)? */
};
Index: cifs-2.6/fs/cifs/connect.c
===================================================================
--- cifs-2.6.orig/fs/cifs/connect.c
+++ cifs-2.6/fs/cifs/connect.c
@@ -1773,6 +1773,8 @@ cifs_put_tcon(struct cifsTconInfo *tcon)
list_del_init(&tcon->tcon_list);
write_unlock(&cifs_tcp_ses_lock);
+ cifs_fscache_release_super_cookie(tcon);
+
xid = GetXid();
CIFSSMBTDis(xid, tcon);
_FreeXid(xid);
@@ -1843,6 +1845,8 @@ cifs_get_tcon(struct cifsSesInfo *ses, s
tcon->nocase = volume_info->nocase;
tcon->local_lease = volume_info->local_lease;
+ cifs_fscache_get_super_cookie(tcon);
+
write_lock(&cifs_tcp_ses_lock);
list_add(&tcon->tcon_list, &ses->tcon_list);
write_unlock(&cifs_tcp_ses_lock);
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.c
+++ cifs-2.6/fs/cifs/fscache.c
@@ -45,3 +45,20 @@ void cifs_fscache_release_client_cookie(
server->fscache = NULL;
}
+void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon)
+{
+ tcon->fscache =
+ fscache_acquire_cookie(tcon->ses->server->fscache,
+ &cifs_fscache_super_index_def, tcon);
+ cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)\n",
+ tcon, tcon->fscache);
+}
+
+void cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon)
+{
+ cFYI(1, "CIFS: releasing superblock cookie (0x%p/0x%p)\n",
+ tcon, tcon->fscache);
+ fscache_relinquish_cookie(tcon->fscache, 0);
+ tcon->fscache = NULL;
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -28,6 +28,7 @@
extern struct fscache_netfs cifs_fscache_netfs;
extern const struct fscache_cookie_def cifs_fscache_server_index_def;
+extern const struct fscache_cookie_def cifs_fscache_super_index_def;
extern int cifs_fscache_register(void);
extern void cifs_fscache_unregister(void);
@@ -37,6 +38,8 @@ extern void cifs_fscache_unregister(void
*/
extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
+extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
+extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
@@ -46,6 +49,9 @@ static inline void
cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
static inline void
cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
+static inline void cifs_fscache_get_super_cookie(struct cifsTconInfo *tcon) {}
+static inline void
+cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
#endif /* CONFIG_CIFS_FSCACHE */
^ permalink raw reply [flat|nested] 56+ messages in thread
* [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] <yes>
` (6 preceding siblings ...)
2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
` (11 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells
Define inode-level data storage objects (managed by cifsInodeInfo structs).
Each inode-level object is created in a super-block level object and is itself
a data storage object in to which pages from the inode are stored.
The inode object is keyed by UniqueId. The coherency data being used is
LastWriteTime and the file size.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
fs/cifs/cache.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/cifsfs.c | 7 ++++
fs/cifs/cifsglob.h | 3 +
fs/cifs/file.c | 6 +++
fs/cifs/fscache.c | 68 +++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/fscache.h | 12 +++++++
fs/cifs/inode.c | 4 ++
7 files changed, 180 insertions(+)
Index: cifs-2.6/fs/cifs/cache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cache.c
+++ cifs-2.6/fs/cifs/cache.c
@@ -138,3 +138,83 @@ const struct fscache_cookie_def cifs_fsc
.get_key = cifs_super_get_key,
};
+/*
+ * Auxiliary data attached to CIFS inode within the cache
+ */
+struct cifs_fscache_inode_auxdata {
+ struct timespec last_write_time;
+ loff_t size;
+};
+
+static uint16_t cifs_fscache_inode_get_key(const void *cookie_netfs_data,
+ void *buffer, uint16_t maxbuf)
+{
+ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+ uint16_t keylen;
+
+ /* use the UniqueId as the key */
+ keylen = sizeof(cifsi->uniqueid);
+ if (keylen > maxbuf)
+ keylen = 0;
+ else
+ memcpy(buffer, &cifsi->uniqueid, keylen);
+
+ return keylen;
+}
+
+static void
+cifs_fscache_inode_get_attr(const void *cookie_netfs_data, uint64_t *size)
+{
+ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+ *size = cifsi->vfs_inode.i_size;
+}
+
+static uint16_t
+cifs_fscache_inode_get_aux(const void *cookie_netfs_data, void *buffer,
+ uint16_t maxbuf)
+{
+ struct cifs_fscache_inode_auxdata auxdata;
+ const struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+ memset(&auxdata, 0, sizeof(auxdata));
+ auxdata.size = cifsi->vfs_inode.i_size;
+ auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
+
+ if (maxbuf > sizeof(auxdata))
+ maxbuf = sizeof(auxdata);
+
+ memcpy(buffer, &auxdata, maxbuf);
+
+ return maxbuf;
+}
+
+static enum
+fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
+ const void *data,
+ uint16_t datalen)
+{
+ struct cifs_fscache_inode_auxdata auxdata;
+ struct cifsInodeInfo *cifsi = cookie_netfs_data;
+
+ if (datalen != sizeof(auxdata))
+ return FSCACHE_CHECKAUX_OBSOLETE;
+
+ memset(&auxdata, 0, sizeof(auxdata));
+ auxdata.size = cifsi->vfs_inode.i_size;
+ auxdata.last_write_time = cifsi->vfs_inode.i_ctime;
+
+ if (memcmp(data, &auxdata, datalen) != 0)
+ return FSCACHE_CHECKAUX_OBSOLETE;
+
+ return FSCACHE_CHECKAUX_OKAY;
+}
+
+const struct fscache_cookie_def cifs_fscache_inode_object_def = {
+ .name = "CIFS.uniqueid",
+ .type = FSCACHE_COOKIE_TYPE_DATAFILE,
+ .get_key = cifs_fscache_inode_get_key,
+ .get_attr = cifs_fscache_inode_get_attr,
+ .get_aux = cifs_fscache_inode_get_aux,
+ .check_aux = cifs_fscache_inode_check_aux,
+};
Index: cifs-2.6/fs/cifs/cifsfs.c
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsfs.c
+++ cifs-2.6/fs/cifs/cifsfs.c
@@ -330,6 +330,12 @@ cifs_destroy_inode(struct inode *inode)
}
static void
+cifs_clear_inode(struct inode *inode)
+{
+ cifs_fscache_release_inode_cookie(inode);
+}
+
+static void
cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
{
seq_printf(s, ",addr=");
@@ -490,6 +496,7 @@ static const struct super_operations cif
.alloc_inode = cifs_alloc_inode,
.destroy_inode = cifs_destroy_inode,
.drop_inode = cifs_drop_inode,
+ .clear_inode = cifs_clear_inode,
/* .delete_inode = cifs_delete_inode, */ /* Do not need above
function unless later we add lazy close of inodes or unless the
kernel forgets to call us with the same number of releases (closes)
Index: cifs-2.6/fs/cifs/cifsglob.h
===================================================================
--- cifs-2.6.orig/fs/cifs/cifsglob.h
+++ cifs-2.6/fs/cifs/cifsglob.h
@@ -407,6 +407,9 @@ struct cifsInodeInfo {
bool invalid_mapping:1; /* pagecache is invalid */
u64 server_eof; /* current file size on server */
u64 uniqueid; /* server inode number */
+#ifdef CONFIG_CIFS_FSCACHE
+ struct fscache_cookie *fscache;
+#endif
struct inode vfs_inode;
};
Index: cifs-2.6/fs/cifs/file.c
===================================================================
--- cifs-2.6.orig/fs/cifs/file.c
+++ cifs-2.6/fs/cifs/file.c
@@ -40,6 +40,7 @@
#include "cifs_unicode.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
+#include "fscache.h"
static inline int cifs_convert_flags(unsigned int flags)
{
@@ -282,6 +283,9 @@ int cifs_open(struct inode *inode, struc
CIFSSMBClose(xid, tcon, netfid);
rc = -ENOMEM;
}
+
+ cifs_fscache_set_inode_cookie(inode, file);
+
goto out;
} else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
if (tcon->ses->serverNOS)
@@ -373,6 +377,8 @@ int cifs_open(struct inode *inode, struc
goto out;
}
+ cifs_fscache_set_inode_cookie(inode, file);
+
if (oplock & CIFS_CREATE_ACTION) {
/* time to set mode which we can not set earlier due to
problems creating new read-only files */
Index: cifs-2.6/fs/cifs/fscache.c
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.c
+++ cifs-2.6/fs/cifs/fscache.c
@@ -62,3 +62,71 @@ void cifs_fscache_release_super_cookie(s
tcon->fscache = NULL;
}
+static void cifs_fscache_enable_inode_cookie(struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+
+ if (cifsi->fscache)
+ return;
+
+ cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+ &cifs_fscache_inode_object_def,
+ cifsi);
+ cFYI(1, "CIFS: got FH cookie (0x%p/0x%p/0x%p)\n",
+ cifs_sb->tcon, cifsi, cifsi->fscache);
+}
+
+void cifs_fscache_release_inode_cookie(struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+ if (cifsi->fscache) {
+ cFYI(1, "CIFS releasing inode cookie (0x%p/0x%p)\n",
+ cifsi, cifsi->fscache);
+ fscache_relinquish_cookie(cifsi->fscache, 0);
+ cifsi->fscache = NULL;
+ }
+}
+
+static void cifs_fscache_disable_inode_cookie(struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+ if (cifsi->fscache) {
+ cFYI(1, "CIFS disabling inode cookie (0x%p/0x%p)\n",
+ cifsi, cifsi->fscache);
+ fscache_relinquish_cookie(cifsi->fscache, 1);
+ cifsi->fscache = NULL;
+ }
+}
+
+void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
+{
+ /* BB: parallel opens - need locking? */
+ if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
+ cifs_fscache_disable_inode_cookie(inode);
+ else {
+ cifs_fscache_enable_inode_cookie(inode);
+ cFYI(1, "CIFS: fscache inode cookie set\n");
+ }
+}
+
+void cifs_fscache_reset_inode_cookie(struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct fscache_cookie *old = cifsi->fscache;
+
+ if (cifsi->fscache) {
+ /* retire the current fscache cache and get a new one */
+ fscache_relinquish_cookie(cifsi->fscache, 1);
+
+ cifsi->fscache = fscache_acquire_cookie(cifs_sb->tcon->fscache,
+ &cifs_fscache_inode_object_def,
+ cifsi);
+ cFYI(1, "CIFS: new cookie (0x%p/0x%p) oldcookie 0x%p\n",
+ cifsi, cifsi->fscache, old);
+ }
+}
+
Index: cifs-2.6/fs/cifs/fscache.h
===================================================================
--- cifs-2.6.orig/fs/cifs/fscache.h
+++ cifs-2.6/fs/cifs/fscache.h
@@ -29,6 +29,8 @@
extern struct fscache_netfs cifs_fscache_netfs;
extern const struct fscache_cookie_def cifs_fscache_server_index_def;
extern const struct fscache_cookie_def cifs_fscache_super_index_def;
+extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
+
extern int cifs_fscache_register(void);
extern void cifs_fscache_unregister(void);
@@ -41,6 +43,10 @@ extern void cifs_fscache_release_client_
extern void cifs_fscache_get_super_cookie(struct cifsTconInfo *);
extern void cifs_fscache_release_super_cookie(struct cifsTconInfo *);
+extern void cifs_fscache_release_inode_cookie(struct inode *);
+extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
+extern void cifs_fscache_reset_inode_cookie(struct inode *);
+
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
@@ -53,6 +59,12 @@ static inline void cifs_fscache_get_supe
static inline void
cifs_fscache_release_super_cookie(struct cifsTconInfo *tcon) {}
+static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
+ struct file *filp) {}
+static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
+
+
#endif /* CONFIG_CIFS_FSCACHE */
#endif /* _CIFS_FSCACHE_H */
Index: cifs-2.6/fs/cifs/inode.c
===================================================================
--- cifs-2.6.orig/fs/cifs/inode.c
+++ cifs-2.6/fs/cifs/inode.c
@@ -29,6 +29,7 @@
#include "cifsproto.h"
#include "cifs_debug.h"
#include "cifs_fs_sb.h"
+#include "fscache.h"
static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
@@ -776,6 +777,8 @@ retry_iget5_locked:
inode->i_flags |= S_NOATIME | S_NOCMTIME;
if (inode->i_state & I_NEW) {
inode->i_ino = hash;
+ /* initialize per-inode cache cookie pointer */
+ CIFS_I(inode)->fscache = NULL;
unlock_new_inode(inode);
}
}
@@ -1568,6 +1571,7 @@ cifs_invalidate_mapping(struct inode *in
cifs_i->write_behind_rc = rc;
}
invalidate_remote_inode(inode);
+ cifs_fscache_reset_inode_cookie(inode);
}
int cifs_revalidate_file(struct file *filp)
^ permalink raw reply [flat|nested] 56+ messages in thread
* [RFC][PATCH 07/10] cifs: FS-Cache page management
[not found] <yes>
` (7 preceding siblings ...)
2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
@ 2010-06-22 15:23 ` Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
` (10 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:23 UTC (permalink / raw)
To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells
Takes care of invalidation and release of FS-Cache marked pages and also
invalidation of the FsCache page flag when the inode is removed.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
fs/cifs/cache.c | 31 +++++++++++++++++++++++++++++++
fs/cifs/file.c | 20 ++++++++++++++++++++
fs/cifs/fscache.c | 26 ++++++++++++++++++++++++++
fs/cifs/fscache.h | 16 ++++++++++++++++
4 files changed, 93 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index b205424..3a733c1 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -210,6 +210,36 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
return FSCACHE_CHECKAUX_OKAY;
}
+static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
+{
+ struct cifsInodeInfo *cifsi = cookie_netfs_data;
+ struct pagevec pvec;
+ pgoff_t first;
+ int loop, nr_pages;
+
+ pagevec_init(&pvec, 0);
+ first = 0;
+
+ cFYI(1, "cifs inode 0x%p now uncached\n", cifsi);
+
+ for (;;) {
+ nr_pages = pagevec_lookup(&pvec,
+ cifsi->vfs_inode.i_mapping, first,
+ PAGEVEC_SIZE - pagevec_count(&pvec));
+ if (!nr_pages)
+ break;
+
+ for (loop = 0; loop < nr_pages; loop++)
+ ClearPageFsCache(pvec.pages[loop]);
+
+ first = pvec.pages[nr_pages - 1]->index + 1;
+
+ pvec.nr = nr_pages;
+ pagevec_release(&pvec);
+ cond_resched();
+ }
+}
+
const struct fscache_cookie_def cifs_fscache_inode_object_def = {
.name = "CIFS.uniqueid",
.type = FSCACHE_COOKIE_TYPE_DATAFILE,
@@ -217,4 +247,5 @@ const struct fscache_cookie_def cifs_fscache_inode_object_def = {
.get_attr = cifs_fscache_inode_get_attr,
.get_aux = cifs_fscache_inode_get_aux,
.check_aux = cifs_fscache_inode_check_aux,
+ .now_uncached = cifs_fscache_inode_now_uncached,
};
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 55ecb55..786ec04 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2271,6 +2271,22 @@ out:
return rc;
}
+static int cifs_release_page(struct page *page, gfp_t gfp)
+{
+ if (PagePrivate(page))
+ return 0;
+
+ return cifs_fscache_release_page(page, gfp);
+}
+
+static void cifs_invalidate_page(struct page *page, unsigned long offset)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
+
+ if (offset == 0)
+ cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
+}
+
static void
cifs_oplock_break(struct slow_work *work)
{
@@ -2344,6 +2360,8 @@ const struct address_space_operations cifs_addr_ops = {
.write_begin = cifs_write_begin,
.write_end = cifs_write_end,
.set_page_dirty = __set_page_dirty_nobuffers,
+ .releasepage = cifs_release_page,
+ .invalidatepage = cifs_invalidate_page,
/* .sync_page = cifs_sync_page, */
/* .direct_IO = */
};
@@ -2360,6 +2378,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
.write_begin = cifs_write_begin,
.write_end = cifs_write_end,
.set_page_dirty = __set_page_dirty_nobuffers,
+ .releasepage = cifs_release_page,
+ .invalidatepage = cifs_invalidate_page,
/* .sync_page = cifs_sync_page, */
/* .direct_IO = */
};
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index ddfd355..c09d3b8 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -130,3 +130,29 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
}
}
+int cifs_fscache_release_page(struct page *page, gfp_t gfp)
+{
+ if (PageFsCache(page)) {
+ struct inode *inode = page->mapping->host;
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+
+ cFYI(1, "CIFS: fscache release page (0x%p/0x%p)\n",
+ cifsi->fscache, page);
+ if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
+ return 0;
+ }
+
+ return 1;
+}
+
+void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
+{
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct fscache_cookie *cookie = cifsi->fscache;
+
+ cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
+ cookie, page, cifsi);
+ fscache_wait_on_page_write(cookie, page);
+ fscache_uncache_page(cookie, page);
+}
+
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 836bb02..127cb0a 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -47,6 +47,16 @@ extern void cifs_fscache_release_inode_cookie(struct inode *);
extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
extern void cifs_fscache_reset_inode_cookie(struct inode *);
+extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
+extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
+
+static inline void cifs_fscache_invalidate_page(struct page *page,
+ struct inode *inode)
+{
+ if (PageFsCache(page))
+ __cifs_fscache_invalidate_page(page, inode);
+}
+
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
@@ -63,7 +73,13 @@ static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
struct file *filp) {}
static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
+static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
+{
+ return 1; /* May release page */
+}
+static inline int cifs_fscache_invalidate_page(struct page *page,
+ struct inode *) {}
#endif /* CONFIG_CIFS_FSCACHE */
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 08/10] cifs: store pages into local cache
[not found] <yes>
` (8 preceding siblings ...)
2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
@ 2010-06-22 15:24 ` Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
` (9 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:24 UTC (permalink / raw)
To: Steve French; +Cc: linux-cifs, linux-fsdevel, linux-kernel, David Howells
Store pages from an CIFS inode into the data storage object associated with
that inode.
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
---
fs/cifs/file.c | 6 ++++++
fs/cifs/fscache.c | 13 +++++++++++++
fs/cifs/fscache.h | 11 +++++++++++
3 files changed, 30 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 786ec04..39c1ce0 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2060,6 +2060,8 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
we will hit it on next read */
/* break; */
+ /* send this page to FS-Cache */
+ cifs_readpage_to_fscache(mapping->host, page);
}
} else {
cFYI(1, "No bytes read (%d) at offset %lld . "
@@ -2117,6 +2119,10 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
flush_dcache_page(page);
SetPageUptodate(page);
+
+ /* send this page to the cache */
+ cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
+
rc = 0;
io_error:
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index c09d3b8..13e47d5 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -145,6 +145,19 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
return 1;
}
+void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
+{
+ int ret;
+
+ cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p\n",
+ CIFS_I(inode)->fscache, page, inode);
+ ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
+ cFYI(1, "CIFS: fscache_write_page returned %d\n", ret);
+
+ if (ret != 0)
+ fscache_uncache_page(CIFS_I(inode)->fscache, page);
+}
+
void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
{
struct cifsInodeInfo *cifsi = CIFS_I(inode);
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index 127cb0a..e34d8ab 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -50,6 +50,8 @@ extern void cifs_fscache_reset_inode_cookie(struct inode *);
extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
+extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
+
static inline void cifs_fscache_invalidate_page(struct page *page,
struct inode *inode)
{
@@ -57,6 +59,13 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
__cifs_fscache_invalidate_page(page, inode);
}
+static inline void cifs_readpage_to_fscache(struct inode *inode,
+ struct page *page)
+{
+ if (PageFsCache(page))
+ __cifs_readpage_to_fscache(inode, page);
+}
+
#else /* CONFIG_CIFS_FSCACHE */
static inline int cifs_fscache_register(void) { return 0; }
static inline void cifs_fscache_unregister(void) {}
@@ -80,6 +89,8 @@ static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
static inline int cifs_fscache_invalidate_page(struct page *page,
struct inode *) {}
+static inline void cifs_readpage_to_fscache(struct inode *inode,
+ struct page *page) {}
#endif /* CONFIG_CIFS_FSCACHE */
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 09/10] cifs: read pages from FS-Cache
[not found] <yes>
` (9 preceding siblings ...)
2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
@ 2010-06-22 15:24 ` Suresh Jayaraman
2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
` (8 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:24 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
Read pages from a FS-Cache data storage object into a CIFS inode.
Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
---
fs/cifs/file.c | 19 ++++++++++++++
fs/cifs/fscache.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++
fs/cifs/fscache.h | 40 ++++++++++++++++++++++++++++-
3 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 39c1ce0..42d2f25 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1978,6 +1978,16 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
pTcon = cifs_sb->tcon;
+ /*
+ * Reads as many pages as possible from fscache. Returns -ENOBUFS
+ * immediately if the cookie is negative
+ */
+ rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
+ &num_pages);
+ cFYI(1, "CIFS: readpages_from_fscache returned %d\n", rc);
+ if (rc == 0)
+ goto read_complete;
+
cFYI(DBG2, "rpages: num pages %d", num_pages);
for (i = 0; i < num_pages; ) {
unsigned contig_pages;
@@ -2090,6 +2100,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
smb_read_data = NULL;
}
+read_complete:
FreeXid(xid);
return rc;
}
@@ -2100,6 +2111,12 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
char *read_data;
int rc;
+ /* Is the page cached? */
+ rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
+ cFYI(1, "CIFS: cifs_readpage_from_fscache returned %d\n", rc);
+ if (rc == 0)
+ goto read_complete;
+
page_cache_get(page);
read_data = kmap(page);
/* for reads over a certain size could initiate async read ahead */
@@ -2128,6 +2145,8 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
io_error:
kunmap(page);
page_cache_release(page);
+
+read_complete:
return rc;
}
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 13e47d5..6813737 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -145,6 +145,79 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
return 1;
}
+static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
+ int error)
+{
+ cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)\n",
+ page, error);
+ if (!error)
+ SetPageUptodate(page);
+ unlock_page(page);
+}
+
+/*
+ * Retrieve a page from FS-Cache
+ */
+int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+ int ret;
+
+ cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p\n",
+ CIFS_I(inode)->fscache, page, inode);
+ ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
+ cifs_readpage_from_fscache_complete,
+ NULL,
+ GFP_KERNEL);
+ switch (ret) {
+
+ case 0: /* page found in fscache, read submitted */
+ cFYI(1, "CIFS: readpage_from_fscache: submitted\n");
+ return ret;
+ case -ENOBUFS: /* page won't be cached */
+ case -ENODATA: /* page not in cache */
+ cFYI(1, "CIFS: readpage_from_fscache %d\n", ret);
+ return 1;
+
+ default:
+ cFYI(1, "unknown error ret = %d", ret);
+ }
+ return ret;
+}
+
+/*
+ * Retrieve a set of pages from FS-Cache
+ */
+int __cifs_readpages_from_fscache(struct inode *inode,
+ struct address_space *mapping,
+ struct list_head *pages,
+ unsigned *nr_pages)
+{
+ int ret;
+
+ cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)\n",
+ CIFS_I(inode)->fscache, *nr_pages, inode);
+ ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
+ pages, nr_pages,
+ cifs_readpage_from_fscache_complete,
+ NULL,
+ mapping_gfp_mask(mapping));
+ switch (ret) {
+ case 0: /* read submitted to the cache for all pages */
+ cFYI(1, "CIFS: readpages_from_fscache\n");
+ return ret;
+
+ case -ENOBUFS: /* some pages are not cached and can't be */
+ case -ENODATA: /* some pages are not cached */
+ cFYI(1, "CIFS: readpages_from_fscache: no page\n");
+ return 1;
+
+ default:
+ cFYI(1, "unknown error ret = %d", ret);
+ }
+
+ return ret;
+}
+
void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
{
int ret;
diff --git a/fs/cifs/fscache.h b/fs/cifs/fscache.h
index e34d8ab..03bd3fe 100644
--- a/fs/cifs/fscache.h
+++ b/fs/cifs/fscache.h
@@ -31,7 +31,6 @@ extern const struct fscache_cookie_def cifs_fscache_server_index_def;
extern const struct fscache_cookie_def cifs_fscache_super_index_def;
extern const struct fscache_cookie_def cifs_fscache_inode_object_def;
-
extern int cifs_fscache_register(void);
extern void cifs_fscache_unregister(void);
@@ -49,6 +48,11 @@ extern void cifs_fscache_reset_inode_cookie(struct inode *);
extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
+extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
+extern int __cifs_readpages_from_fscache(struct inode *,
+ struct address_space *,
+ struct list_head *,
+ unsigned *);
extern void __cifs_readpage_to_fscache(struct inode *, struct page *);
@@ -59,6 +63,26 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
__cifs_fscache_invalidate_page(page, inode);
}
+static inline int cifs_readpage_from_fscache(struct inode *inode,
+ struct page *page)
+{
+ if (CIFS_I(inode)->fscache)
+ return __cifs_readpage_from_fscache(inode, page);
+
+ return -ENOBUFS;
+}
+
+static inline int cifs_readpages_from_fscache(struct inode *inode,
+ struct address_space *mapping,
+ struct list_head *pages,
+ unsigned *nr_pages)
+{
+ if (CIFS_I(inode)->fscache)
+ return __cifs_readpages_from_fscache(inode, mapping, pages,
+ nr_pages);
+ return -ENOBUFS;
+}
+
static inline void cifs_readpage_to_fscache(struct inode *inode,
struct page *page)
{
@@ -89,6 +113,20 @@ static inline void cifs_fscache_release_page(struct page *page, gfp_t gfp)
static inline int cifs_fscache_invalidate_page(struct page *page,
struct inode *) {}
+static inline int
+cifs_readpage_from_fscache(struct inode *inode, struct page *page)
+{
+ return -ENOBUFS;
+}
+
+static inline int cifs_readpages_from_fscache(struct inode *inode,
+ struct address_space *mapping,
+ struct list_head *pages,
+ unsigned *nr_pages)
+{
+ return -ENOBUFS;
+}
+
static inline void cifs_readpage_to_fscache(struct inode *inode,
struct page *page) {}
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [RFC][PATCH 10/10] cifs: add mount option to enable local caching
[not found] <yes>
` (10 preceding siblings ...)
2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
@ 2010-06-22 15:25 ` Suresh Jayaraman
2010-06-23 18:32 ` Scott Lovenberg
[not found] ` <1277220189-3485-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
` (7 subsequent siblings)
19 siblings, 1 reply; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-22 15:25 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
Add a mount option 'fsc' to enable local caching on CIFS.
As the cifs-utils (userspace) changes are not done yet, this patch enables
'fsc' by default to assist testing.
Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
---
fs/cifs/cifs_fs_sb.h | 1 +
fs/cifs/connect.c | 8 ++++++++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h
index 246a167..9e77145 100644
--- a/fs/cifs/cifs_fs_sb.h
+++ b/fs/cifs/cifs_fs_sb.h
@@ -35,6 +35,7 @@
#define CIFS_MOUNT_DYNPERM 0x1000 /* allow in-memory only mode setting */
#define CIFS_MOUNT_NOPOSIXBRL 0x2000 /* mandatory not posix byte range lock */
#define CIFS_MOUNT_NOSSYNC 0x4000 /* don't do slow SMBflush on every sync*/
+#define CIFS_MOUNT_FSCACHE 0x8000 /* local caching enabled */
struct cifs_sb_info {
struct cifsTconInfo *tcon; /* primary mount */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 4844dbd..6c6ff3c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -98,6 +98,7 @@ struct smb_vol {
bool noblocksnd:1;
bool noautotune:1;
bool nostrictsync:1; /* do not force expensive SMBflush on every sync */
+ bool fsc:1; /* enable fscache */
unsigned int rsize;
unsigned int wsize;
bool sockopt_tcp_nodelay:1;
@@ -843,6 +844,9 @@ cifs_parse_mount_options(char *options, const char *devname,
/* default to using server inode numbers where available */
vol->server_ino = 1;
+ /* XXX: default to fsc for testing until mount.cifs pieces are done */
+ vol->fsc = 1;
+
if (!options)
return 1;
@@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const char *devname,
printk(KERN_WARNING "CIFS: Mount option noac not "
"supported. Instead set "
"/proc/fs/cifs/LookupCacheEnabled to 0\n");
+ } else if (strnicmp(data, "fsc", 3) == 0) {
+ vol->fsc = true;
} else
printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
data);
@@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
if (pvolume_info->dynperm)
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
+ if (pvolume_info->fsc)
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
if (pvolume_info->direct_io) {
cFYI(1, "mounting share using direct i/o");
cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
--
1.6.4.2
^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion
[not found] ` <1277220170-3442-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-22 21:37 ` Jeff Layton
0 siblings, 0 replies; 56+ messages in thread
From: Jeff Layton @ 2010-06-22 21:37 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
On Tue, 22 Jun 2010 20:52:50 +0530
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Add conditional compile macros to guard the header file against multiple
> inclusion.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
> ---
> fs/cifs/cifsglob.h | 5 +++++
> 1 files changed, 5 insertions(+), 0 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index a88479c..6b2c39d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -16,6 +16,9 @@
> * the GNU Lesser General Public License for more details.
> *
> */
> +#ifndef _CIFS_GLOB_H
> +#define _CIFS_GLOB_H
> +
> #include <linux/in.h>
> #include <linux/in6.h>
> #include <linux/slab.h>
> @@ -733,3 +736,5 @@ GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */
> GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/
>
> extern const struct slow_work_ops cifs_oplock_break_ops;
> +
> +#endif /* _CIFS_GLOB_H */
Strong ACK
Acked-by: Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
[not found] ` <1277220198-3522-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-22 21:52 ` Jeff Layton
[not found] ` <20100622175214.4c56234f-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
0 siblings, 1 reply; 56+ messages in thread
From: Jeff Layton @ 2010-06-22 21:52 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
On Tue, 22 Jun 2010 20:53:18 +0530
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Define server-level cache index objects (as managed by TCP_ServerInfo structs).
> Each server object is created in the CIFS top-level index object and is itself
> an index into which superblock-level objects are inserted.
>
> Currently, the server objects are keyed by hostname.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
> ---
> fs/cifs/Makefile | 2 +-
> fs/cifs/cache.c | 25 +++++++++++++++++++++++++
> fs/cifs/cifsglob.h | 3 +++
> fs/cifs/connect.c | 4 ++++
> fs/cifs/fscache.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
> fs/cifs/fscache.h | 12 ++++++++++++
> 6 files changed, 92 insertions(+), 1 deletion(-)
> create mode 100644 fs/cifs/fscache.c
>
> Index: cifs-2.6/fs/cifs/Makefile
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/Makefile
> +++ cifs-2.6/fs/cifs/Makefile
> @@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
>
> cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>
> -cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
> +cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
> Index: cifs-2.6/fs/cifs/cache.c
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/cache.c
> +++ cifs-2.6/fs/cifs/cache.c
> @@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
> fscache_unregister_netfs(&cifs_fscache_netfs);
> }
>
> +/*
> + * Server object currently keyed by hostname
> + */
> +static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
> + void *buffer, uint16_t maxbuf)
> +{
> + const struct TCP_Server_Info *server = cookie_netfs_data;
> + uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
> +
Would a tuple of address/family/port be a better choice here? Imagine I
mount "foo" and then later mount "foor.bar.baz". If they are the same
address and only the UNC differs, then you won't get the benefit of
the cache, right?
> + if (len > maxbuf)
> + return 0;
> +
> + memcpy(buffer, server->hostname, len);
> +
> + return len;
> +}
> +
> +/*
> + * Server object for FS-Cache
> + */
> +const struct fscache_cookie_def cifs_fscache_server_index_def = {
> + .name = "CIFS.server",
> + .type = FSCACHE_COOKIE_TYPE_INDEX,
> + .get_key = cifs_server_get_key,
> +};
> Index: cifs-2.6/fs/cifs/cifsglob.h
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/cifsglob.h
> +++ cifs-2.6/fs/cifs/cifsglob.h
> @@ -193,6 +193,9 @@ struct TCP_Server_Info {
> bool sec_mskerberos; /* supports legacy MS Kerberos */
> bool sec_kerberosu2u; /* supports U2U Kerberos */
> bool sec_ntlmssp; /* supports NTLMSSP */
> +#ifdef CONFIG_CIFS_FSCACHE
> + struct fscache_cookie *fscache; /* client index cache cookie */
> +#endif
> };
>
> /*
> Index: cifs-2.6/fs/cifs/connect.c
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/connect.c
> +++ cifs-2.6/fs/cifs/connect.c
> @@ -48,6 +48,7 @@
> #include "nterr.h"
> #include "rfc1002pdu.h"
> #include "cn_cifs.h"
> +#include "fscache.h"
>
> #define CIFS_PORT 445
> #define RFC1001_PORT 139
> @@ -1453,6 +1454,8 @@ cifs_put_tcp_session(struct TCP_Server_I
> return;
> }
>
> + cifs_fscache_release_client_cookie(server);
> +
> list_del_init(&server->tcp_ses_list);
> write_unlock(&cifs_tcp_ses_lock);
>
> @@ -1572,6 +1575,7 @@ cifs_get_tcp_session(struct smb_vol *vol
> goto out_err;
> }
>
> + cifs_fscache_get_client_cookie(tcp_ses);
> /* thread spawned, put it on the list */
> write_lock(&cifs_tcp_ses_lock);
> list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list);
> Index: cifs-2.6/fs/cifs/fscache.c
> ===================================================================
> --- /dev/null
> +++ cifs-2.6/fs/cifs/fscache.c
> @@ -0,0 +1,47 @@
> +/*
> + * fs/cifs/fscache.c - CIFS filesystem cache interface
> + *
> + * Copyright (c) 2010 Novell, Inc.
> + * Authors(s): Suresh Jayaraman (sjayaraman-l3A5Bk7waGM@public.gmane.org>
> + *
> + * This library is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License as published
> + * by the Free Software Foundation; either version 2.1 of the License, or
> + * (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> + * the GNU Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public License
> + * along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + */
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <linux/sched.h>
> +#include <linux/mm.h>
> +#include <linux/in6.h>
> +
> +#include "fscache.h"
> +#include "cifsglob.h"
> +#include "cifs_debug.h"
> +
> +void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
> +{
> + server->fscache =
> + fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
> + &cifs_fscache_server_index_def, server);
> + cFYI(1, "CIFS: get client cookie (0x%p/0x%p)\n",
> + server, server->fscache);
> +}
> +
> +void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
> +{
> + cFYI(1, "CIFS: release client cookie (0x%p/0x%p)\n",
> + server, server->fscache);
> + fscache_relinquish_cookie(server->fscache, 0);
> + server->fscache = NULL;
> +}
> +
> Index: cifs-2.6/fs/cifs/fscache.h
> ===================================================================
> --- cifs-2.6.orig/fs/cifs/fscache.h
> +++ cifs-2.6/fs/cifs/fscache.h
> @@ -27,14 +27,26 @@
> #ifdef CONFIG_CIFS_FSCACHE
>
> extern struct fscache_netfs cifs_fscache_netfs;
> +extern const struct fscache_cookie_def cifs_fscache_server_index_def;
>
> extern int cifs_fscache_register(void);
> extern void cifs_fscache_unregister(void);
>
> +/*
> + * fscache.c
> + */
> +extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *);
> +extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *);
> +
> #else /* CONFIG_CIFS_FSCACHE */
> static inline int cifs_fscache_register(void) { return 0; }
> static inline void cifs_fscache_unregister(void) {}
>
> +static inline void
> +cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {}
> +static inline void
> +cifs_fscache_get_client_cookie(struct TCP_Server_Info *server); {}
> +
> #endif /* CONFIG_CIFS_FSCACHE */
>
> #endif /* _CIFS_FSCACHE_H */
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Jeff Layton <jlayton-vpEMnDpepFuMZCB2o+C8xQ@public.gmane.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
[not found] ` <20100622175214.4c56234f-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
@ 2010-06-23 5:34 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-23 5:34 UTC (permalink / raw)
To: Jeff Layton
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
On 06/23/2010 03:22 AM, Jeff Layton wrote:
> On Tue, 22 Jun 2010 20:53:18 +0530
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
>
>> Define server-level cache index objects (as managed by TCP_ServerInfo structs).
>> Each server object is created in the CIFS top-level index object and is itself
>> an index into which superblock-level objects are inserted.
>>
>> Currently, the server objects are keyed by hostname.
>>
>> Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
>> ---
>> fs/cifs/Makefile | 2 +-
>> fs/cifs/cache.c | 25 +++++++++++++++++++++++++
>> fs/cifs/cifsglob.h | 3 +++
>> fs/cifs/connect.c | 4 ++++
>> fs/cifs/fscache.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
>> fs/cifs/fscache.h | 12 ++++++++++++
>> 6 files changed, 92 insertions(+), 1 deletion(-)
>> create mode 100644 fs/cifs/fscache.c
>>
>> Index: cifs-2.6/fs/cifs/Makefile
>> ===================================================================
>> --- cifs-2.6.orig/fs/cifs/Makefile
>> +++ cifs-2.6/fs/cifs/Makefile
>> @@ -12,4 +12,4 @@ cifs-$(CONFIG_CIFS_UPCALL) += cifs_spneg
>>
>> cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o
>>
>> -cifs-$(CONFIG_CIFS_FSCACHE) += cache.o
>> +cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o
>> Index: cifs-2.6/fs/cifs/cache.c
>> ===================================================================
>> --- cifs-2.6.orig/fs/cifs/cache.c
>> +++ cifs-2.6/fs/cifs/cache.c
>> @@ -51,3 +51,28 @@ void cifs_fscache_unregister(void)
>> fscache_unregister_netfs(&cifs_fscache_netfs);
>> }
>>
>> +/*
>> + * Server object currently keyed by hostname
>> + */
>> +static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
>> + void *buffer, uint16_t maxbuf)
>> +{
>> + const struct TCP_Server_Info *server = cookie_netfs_data;
>> + uint16_t len = strnlen(server->hostname, sizeof(server->hostname));
>> +
>
> Would a tuple of address/family/port be a better choice here? Imagine I
> mount "foo" and then later mount "foor.bar.baz". If they are the same
> address and only the UNC differs, then you won't get the benefit of
> the cache, right?
>
Good point. I'll fix it up when I do a respin.
Thanks,
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 03/10] cifs: register CIFS for caching
[not found] ` <1277220189-3485-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 16:51 ` David Howells
[not found] ` <9603.1277311877-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 56+ messages in thread
From: David Howells @ 2010-06-23 16:51 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> + rc = cifs_fscache_register();
> + if (rc)
> + goto out;
> +
> rc = cifs_init_inodecache();
> if (rc)
> goto out_clean_proc;
> @@ -949,8 +954,10 @@ init_cifs(void)
> cifs_destroy_mids();
> out_destroy_inodecache:
> cifs_destroy_inodecache();
> + cifs_fscache_unregister();
> out_clean_proc:
This is incorrect. You need to call cifs_fscache_unregister() if
cifs_init_inodecache() fails.
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache
[not found] <yes>
` (12 preceding siblings ...)
[not found] ` <1277220189-3485-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 16:54 ` David Howells
[not found] ` <1277220206-3559-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
` (5 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 16:54 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel
Suresh Jayaraman <sjayaraman@suse.de> wrote:
> Define server-level cache index objects (as managed by TCP_ServerInfo
> structs). Each server object is created in the CIFS top-level index object
> and is itself an index into which superblock-level objects are inserted.
>
> Currently, the server objects are keyed by hostname.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Looks reasonable, apart from the index key. I agree with Jeff that you
probably want {address,port,family} rather than a hostname.
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
[not found] ` <1277220206-3559-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 16:58 ` David Howells
[not found] ` <9720.1277312290-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
` (2 more replies)
0 siblings, 3 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 16:58 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Define superblock-level cache index objects (managed by cifsTconInfo
> structs). Each superblock object is created in a server-level index object
> and in itself an index into which inode-level objects are inserted.
>
> Currently, the superblock objects are keyed by sharename.
Seems reasonable. Is there any way you can check that the share you are
looking at on a server is the same as the last time you looked? Can you
validate the root directory of the share in some way?
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <1277220214-3597-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 17:02 ` David Howells
[not found] ` <9822.1277312573-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
[not found] ` <4C24A606.5040001-l3A5Bk7waGM@public.gmane.org>
0 siblings, 2 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 17:02 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Define inode-level data storage objects (managed by cifsInodeInfo structs).
> Each inode-level object is created in a super-block level object and is
> itself a data storage object in to which pages from the inode are stored.
>
> The inode object is keyed by UniqueId. The coherency data being used is
> LastWriteTime and the file size.
Isn't there a file creation time too?
I take it you don't support caching on files that are open for writing at this
time?
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 07/10] cifs: FS-Cache page management
[not found] <yes>
` (15 preceding siblings ...)
[not found] ` <1277220214-3597-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 17:05 ` David Howells
[not found] ` <1277220240-3674-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
` (2 subsequent siblings)
19 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 17:05 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel
Suresh Jayaraman <sjayaraman@suse.de> wrote:
> Takes care of invalidation and release of FS-Cache marked pages and also
> invalidation of the FsCache page flag when the inode is removed.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Acked-by: David Howells <dhowells@redhat.com>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 08/10] cifs: store pages into local cache
[not found] ` <1277220240-3674-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 17:06 ` David Howells
0 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 17:06 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Store pages from an CIFS inode into the data storage object associated with
> that inode.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
Acked-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 09/10] cifs: read pages from FS-Cache
[not found] ` <1277220261-3717-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 17:07 ` David Howells
0 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 17:07 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> Read pages from a FS-Cache data storage object into a CIFS inode.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org>
Acked-by: David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
[not found] <yes>
` (18 preceding siblings ...)
[not found] ` <1277220261-3717-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-23 17:08 ` David Howells
19 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-23 17:08 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel
Suresh Jayaraman <sjayaraman@suse.de> wrote:
> Add a mount option 'fsc' to enable local caching on CIFS.
>
> As the cifs-utils (userspace) changes are not done yet, this patch enables
> 'fsc' by default to assist testing.
>
> Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
Acked-by: David Howells <dhowells@redhat.com>
(Give or take the debugging bit)
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
@ 2010-06-23 18:32 ` Scott Lovenberg
[not found] ` <4C225338.9010807-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 56+ messages in thread
From: Scott Lovenberg @ 2010-06-23 18:32 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: Steve French, linux-cifs, linux-fsdevel, linux-kernel,
David Howells
On 6/22/2010 11:25 AM, Suresh Jayaraman wrote:
> Add a mount option 'fsc' to enable local caching on CIFS.
>
> As the cifs-utils (userspace) changes are not done yet, this patch enables
> 'fsc' by default to assist testing.
>
[...]
> @@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const char *devname,
> printk(KERN_WARNING "CIFS: Mount option noac not "
> "supported. Instead set "
> "/proc/fs/cifs/LookupCacheEnabled to 0\n");
> + } else if (strnicmp(data, "fsc", 3) == 0) {
> + vol->fsc = true;
> } else
> printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
> data);
> @@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
> if (pvolume_info->dynperm)
> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
> + if (pvolume_info->fsc)
> + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
> if (pvolume_info->direct_io) {
> cFYI(1, "mounting share using direct i/o");
> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
>
I reworked the CIFS mount option parsing a while back; I'm not sure
whether that patch was going to be in the 2.6.35 tree or not (the window
just opened, didn't it?).
Jeff, Steve, can you confirm if that patch is going to be in 2.6.35?
Patch refs: http://patchwork.ozlabs.org/patch/53059/ and
http://patchwork.ozlabs.org/patch/53674/
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 10/10] cifs: add mount option to enable local caching
[not found] ` <4C225338.9010807-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2010-06-25 10:48 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 10:48 UTC (permalink / raw)
To: Scott Lovenberg
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, David Howells
On 06/24/2010 12:02 AM, Scott Lovenberg wrote:
> On 6/22/2010 11:25 AM, Suresh Jayaraman wrote:
>> Add a mount option 'fsc' to enable local caching on CIFS.
>>
>> As the cifs-utils (userspace) changes are not done yet, this patch
>> enables
>> 'fsc' by default to assist testing.
>>
> [...]
>> @@ -1332,6 +1336,8 @@ cifs_parse_mount_options(char *options, const
>> char *devname,
>> printk(KERN_WARNING "CIFS: Mount option noac not "
>> "supported. Instead set "
>> "/proc/fs/cifs/LookupCacheEnabled to 0\n");
>> + } else if (strnicmp(data, "fsc", 3) == 0) {
>> + vol->fsc = true;
>> } else
>> printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
>> data);
>> @@ -2405,6 +2411,8 @@ static void setup_cifs_sb(struct smb_vol
>> *pvolume_info,
>> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_GID;
>> if (pvolume_info->dynperm)
>> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DYNPERM;
>> + if (pvolume_info->fsc)
>> + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_FSCACHE;
>> if (pvolume_info->direct_io) {
>> cFYI(1, "mounting share using direct i/o");
>> cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO;
>>
> I reworked the CIFS mount option parsing a while back; I'm not sure
> whether that patch was going to be in the 2.6.35 tree or not (the window
> just opened, didn't it?).
Not a problem, I could redo this patch alone when the reworked option
parsing patches get in.
> Jeff, Steve, can you confirm if that patch is going to be in 2.6.35?
>
> Patch refs: http://patchwork.ozlabs.org/patch/53059/ and
> http://patchwork.ozlabs.org/patch/53674/
>
Thanks,
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 03/10] cifs: register CIFS for caching
[not found] ` <9603.1277311877-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 10:56 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 10:56 UTC (permalink / raw)
To: David Howells
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 06/23/2010 10:21 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
>
>> + rc = cifs_fscache_register();
>> + if (rc)
>> + goto out;
>> +
>> rc = cifs_init_inodecache();
>> if (rc)
>> goto out_clean_proc;
>> @@ -949,8 +954,10 @@ init_cifs(void)
>> cifs_destroy_mids();
>> out_destroy_inodecache:
>> cifs_destroy_inodecache();
>> + cifs_fscache_unregister();
>> out_clean_proc:
>
> This is incorrect. You need to call cifs_fscache_unregister() if
> cifs_init_inodecache() fails.
>
Doh! I'll fix it.
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
[not found] ` <9720.1277312290-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 12:44 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 12:44 UTC (permalink / raw)
To: David Howells
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 06/23/2010 10:28 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
>
>> Define superblock-level cache index objects (managed by cifsTconInfo
>> structs). Each superblock object is created in a server-level index object
>> and in itself an index into which inode-level objects are inserted.
>>
>> Currently, the superblock objects are keyed by sharename.
>
> Seems reasonable. Is there any way you can check that the share you are
> looking at on a server is the same as the last time you looked? Can you
Good point.
I thought of using TID (Tree identifier; a unique ID for a resource in
use by client) along with sharename. But, Server is free to reuse them
when the tree connection closes and does not guarantee the same Tid for
a particular resource across tree connections.
Also, considering the UNC name of the resource (//server/share) may not
be a good idea too as the cache will not be used when for e.g. IPaddress
is used to mount.
So, if a server does something like this:
- export a share 'foo' (original server path: /export/vol1/foo)
- client mounts and uses it
- server unexports the share 'foo'
- server exports 'foo' (original sever path: /export/vol2/foo)
we have a bit of problem..
> validate the root directory of the share in some way?
>
I don't know if there is a way to do this.
Thanks,
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <9822.1277312573-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 12:50 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-25 12:50 UTC (permalink / raw)
To: David Howells
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 06/23/2010 10:32 PM, David Howells wrote:
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
>
>> Define inode-level data storage objects (managed by cifsInodeInfo structs).
>> Each inode-level object is created in a super-block level object and is
>> itself a data storage object in to which pages from the inode are stored.
>>
>> The inode object is keyed by UniqueId. The coherency data being used is
>> LastWriteTime and the file size.
>
> Isn't there a file creation time too?
I think the creation time is currently being ignored as we won't be able
to accomodate in POSIX stat struct.
> I take it you don't support caching on files that are open for writing at this
> time?
>
Yes.
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <4C24A606.5040001-l3A5Bk7waGM@public.gmane.org>
@ 2010-06-25 12:55 ` David Howells
[not found] ` <22697.1277470549-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 21:46 ` David Howells
0 siblings, 2 replies; 56+ messages in thread
From: David Howells @ 2010-06-25 12:55 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
> I think the creation time is currently being ignored as we won't be able
> to accomodate in POSIX stat struct.
The FS-Cache interface doesn't use the POSIX stat struct, but it could be
really useful to save it and use it for cache coherency inside the kernel.
Out of interest, what does Samba do when it comes to generating a creation time
for UNIX where one does not exist?
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
[not found] ` <9720.1277312290-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 12:58 ` David Howells
[not found] ` <22746.1277470713-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-25 12:58 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel
Suresh Jayaraman <sjayaraman@suse.de> wrote:
> Also, considering the UNC name of the resource (//server/share) may not
> be a good idea too as the cache will not be used when for e.g. IPaddress
> is used to mount.
You could convert the UNC name to an IP address, and just use that as your
key.
> > validate the root directory of the share in some way?
>
> I don't know if there is a way to do this.
Is there an inode number or something? Even the creation time might do.
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
[not found] ` <22746.1277470713-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 13:26 ` David Howells
[not found] ` <23204.1277472412-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-28 13:24 ` David Howells
0 siblings, 2 replies; 56+ messages in thread
From: David Howells @ 2010-06-25 13:26 UTC (permalink / raw)
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Suresh Jayaraman, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > > validate the root directory of the share in some way?
> >
> > I don't know if there is a way to do this.
>
> Is there an inode number or something? Even the creation time might do.
Looking in cifspdu.h, there are a number of things that it might be possible
to use.
(1) FILE_ALL_INFO: CreationTime, IndexNumber, IndexNumber1, FileName
(assuming this isn't flattened to '\' or something for the root of a
share.
(2) FILE_UNIX_BASIC_INFO: DevMajor, DevMinor, UniqueId.
(3) FILE_INFO_STANDARD: CreationDate, CreationTime.
(4) FILE_INFO_BASIC: CreationTime.
(5) FILE_DIRECTORY_INFO: FileIndex, CreationTime, FileName.
(6) SEARCH_ID_FULL_DIR_INFO: FileIndex, CreationTime, UniqueId, FileName.
(7) FILE_BOTH_DIRECTORY_INFO: FileIndex, CreationTime, ShortName, FileName.
(8) OPEN_RSP_EXT: Fid, CreationTime, VolumeGUID, FileId.
You may have to choose different sets of things, depending on what the server
has on offer. Also, don't forget, if you can't work out whether a share is
coherent or not from the above, you can always use LastWriteTime, ChangeTime
and EndOfFile and just discard the whole subtree if they differ.
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <22697.1277470549-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 16:53 ` Jeff Layton
0 siblings, 0 replies; 56+ messages in thread
From: Jeff Layton @ 2010-06-25 16:53 UTC (permalink / raw)
To: David Howells
Cc: Suresh Jayaraman, Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ
On Fri, 25 Jun 2010 13:55:49 +0100
David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> Suresh Jayaraman <sjayaraman-l3A5Bk7waGM@public.gmane.org> wrote:
>
> > I think the creation time is currently being ignored as we won't be able
> > to accomodate in POSIX stat struct.
>
> The FS-Cache interface doesn't use the POSIX stat struct, but it could be
> really useful to save it and use it for cache coherency inside the kernel.
>
> Out of interest, what does Samba do when it comes to generating a creation time
> for UNIX where one does not exist?
>
(cc'ing samba-technical since we're talking about the create time)
Looks like it mostly uses the ctime. IMO, the mtime would be a better
choice since it changes less frequently, but I don't guess that it
matters very much.
I have a few patches that make the cifs_iget code do more stringent
checks. One of those makes it use the create time like an i_generation
field to guard against matching inodes that have the same number but
that have undergone a delete/create cycle. They need a bit more testing
but I'm planning to post them in time for 2.6.36.
Because of how samba generates this number, it could be somewhat
problematic to do this. What may save us though is that Linux<->Samba
mostly uses unix extensions unless someone has specifically disabled
them on either end. The unix extension calls don't generally send any
sort of create time field, so we can't rely on it in those codepaths
anyway.
--
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
2010-06-25 12:55 ` David Howells
[not found] ` <22697.1277470549-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-25 21:46 ` David Howells
2010-06-25 22:26 ` Jeff Layton
[not found] ` <20100625182651.36800d06-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
1 sibling, 2 replies; 56+ messages in thread
From: David Howells @ 2010-06-25 21:46 UTC (permalink / raw)
To: Jeff Layton
Cc: dhowells, Suresh Jayaraman, Steve French, linux-cifs,
linux-fsdevel, linux-kernel, samba-technical
Jeff Layton <jlayton@samba.org> wrote:
> Looks like it mostly uses the ctime. IMO, the mtime would be a better
> choice since it changes less frequently, but I don't guess that it
> matters very much.
I'd've thought mtime changes more frequently since that's altered when data is
written. ctime is changed when attributes are changed.
Note that Ext4 appears to have a file creation time field in its inode
(struct ext4_inode::i_crtime[_extra]). Can Samba be made to use that?
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
2010-06-25 21:46 ` David Howells
@ 2010-06-25 22:26 ` Jeff Layton
2010-06-25 23:05 ` Steve French
[not found] ` <20100625182651.36800d06-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
1 sibling, 1 reply; 56+ messages in thread
From: Jeff Layton @ 2010-06-25 22:26 UTC (permalink / raw)
To: David Howells
Cc: linux-cifs, samba-technical, linux-kernel, Steve French,
linux-fsdevel
On Fri, 25 Jun 2010 22:46:38 +0100
David Howells <dhowells@redhat.com> wrote:
> Jeff Layton <jlayton@samba.org> wrote:
>
> > Looks like it mostly uses the ctime. IMO, the mtime would be a better
> > choice since it changes less frequently, but I don't guess that it
> > matters very much.
>
> I'd've thought mtime changes more frequently since that's altered when data is
> written. ctime is changed when attributes are changed.
>
IIUC, updating mtime for a write is also an attribute change, and that
affects ctime. According to the stat(2) manpage:
The field st_ctime is changed by writing or by setting inode informa-
tion (i.e., owner, group, link count, mode, etc.).
> Note that Ext4 appears to have a file creation time field in its inode
> (struct ext4_inode::i_crtime[_extra]). Can Samba be made to use that?
>
Is it exposed to userspace in any (standard) way? It would be handy to
have that. While we're wishing...it might also be nice to have a
standard way to get at the i_generation from userspace too.
--
Jeff Layton <jlayton@samba.org>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <20100625182651.36800d06-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
@ 2010-06-25 23:04 ` David Howells
0 siblings, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-25 23:04 UTC (permalink / raw)
To: Jeff Layton
Cc: dhowells-H+wXaHxf7aLQT0dZR+AlfA, Suresh Jayaraman, Steve French,
linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ
Jeff Layton <jlayton-eUNUBHrolfbYtjvyW6yDsg@public.gmane.org> wrote:
> IIUC, updating mtime for a write is also an attribute change, and that
> affects ctime. According to the stat(2) manpage:
You're right. Okay, ctime is the more frequently changed.
> > Note that Ext4 appears to have a file creation time field in its inode
> > (struct ext4_inode::i_crtime[_extra]). Can Samba be made to use that?
>
> Is it exposed to userspace in any (standard) way? It would be handy to
> have that. While we're wishing...it might also be nice to have a
> standard way to get at the i_generation from userspace too.
Not at present, but it's something that could be exported by ioctl() or
getxattr().
David
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
2010-06-25 22:26 ` Jeff Layton
@ 2010-06-25 23:05 ` Steve French
2010-06-26 0:52 ` Mingming Cao
0 siblings, 1 reply; 56+ messages in thread
From: Steve French @ 2010-06-25 23:05 UTC (permalink / raw)
To: Jeff Layton, Aneesh Kumar K.V, Mingming Cao
Cc: David Howells, Suresh Jayaraman, linux-cifs, linux-fsdevel,
linux-kernel, samba-technical, Jeff Layton
On Fri, Jun 25, 2010 at 5:26 PM, Jeff Layton <jlayton@samba.org> wrote:
>
> On Fri, 25 Jun 2010 22:46:38 +0100
> David Howells <dhowells@redhat.com> wrote:
>
> > Jeff Layton <jlayton@samba.org> wrote:
> >
> > > Looks like it mostly uses the ctime. IMO, the mtime would be a better
> > > choice since it changes less frequently, but I don't guess that it
> > > matters very much.
> >
> > I'd've thought mtime changes more frequently since that's altered when data is
> > written. ctime is changed when attributes are changed.
> >
>
> IIUC, updating mtime for a write is also an attribute change, and that
> affects ctime. According to the stat(2) manpage:
>
> The field st_ctime is changed by writing or by setting inode informa-
> tion (i.e., owner, group, link count, mode, etc.).
>
> > Note that Ext4 appears to have a file creation time field in its inode
> > (struct ext4_inode::i_crtime[_extra]). Can Samba be made to use that?
> >
>
> Is it exposed to userspace in any (standard) way? It would be handy to
> have that. While we're wishing...it might also be nice to have a
> standard way to get at the i_generation from userspace too.
>
Yes - I have talked with MingMing and Aneesh about those (NFS may
someday be able to use those too). An obstacle in the past had been
that samba server stores its own fake creation time in an ndr encoded
xattr which complicates things.
MingMing/Annesh -
Xattr or other way to get at birth time?
--
Thanks,
Steve
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
2010-06-25 23:05 ` Steve French
@ 2010-06-26 0:52 ` Mingming Cao
2010-06-27 18:17 ` Aneesh Kumar K. V
0 siblings, 1 reply; 56+ messages in thread
From: Mingming Cao @ 2010-06-26 0:52 UTC (permalink / raw)
To: Steve French
Cc: linux-cifs, Jeff Layton, samba-technical, linux-kernel,
David Howells, linux-fsdevel, Aneesh Kumar K.V
Steve French <smfrench@gmail.com> wrote on 06/25/2010 04:05:30 PM:
> Steve French <smfrench@gmail.com>
> 06/25/2010 04:05 PM
>
> To
>
> Jeff Layton <jlayton@samba.org>, "Aneesh Kumar K.V"
> <aneesh.kumar@linux.vnet.ibm.com>, Mingming Cao/Beaverton/IBM@IBMUS
>
> cc
>
> David Howells <dhowells@redhat.com>, Suresh Jayaraman
> <sjayaraman@suse.de>, linux-cifs@vger.kernel.org, linux-
> fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, samba-
> technical@lists.samba.org, Jeff Layton <jlayton@redhat.com>
>
> Subject
>
> Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and
> register them
>
> On Fri, Jun 25, 2010 at 5:26 PM, Jeff Layton <jlayton@samba.org> wrote:
> >
> > On Fri, 25 Jun 2010 22:46:38 +0100
> > David Howells <dhowells@redhat.com> wrote:
> >
> > > Jeff Layton <jlayton@samba.org> wrote:
> > >
> > > > Looks like it mostly uses the ctime. IMO, the mtime would be a
better
> > > > choice since it changes less frequently, but I don't guess that it
> > > > matters very much.
> > >
> > > I'd've thought mtime changes more frequently since that's
> altered when data is
> > > written. ctime is changed when attributes are changed.
> > >
> >
> > IIUC, updating mtime for a write is also an attribute change, and that
> > affects ctime. According to the stat(2) manpage:
> >
> > The field st_ctime is changed by writing or by setting
> inode informa-
> > tion (i.e., owner, group, link count, mode, etc.).
> >
> > > Note that Ext4 appears to have a file creation time field in its
inode
> > > (struct ext4_inode::i_crtime[_extra]). Can Samba be made to use
that?
> > >
> >
> > Is it exposed to userspace in any (standard) way? It would be handy to
> > have that. While we're wishing...it might also be nice to have a
> > standard way to get at the i_generation from userspace too.
> >
>
> Yes - I have talked with MingMing and Aneesh about those (NFS may
> someday be able to use those too). An obstacle in the past had been
> that samba server stores its own fake creation time in an ndr encoded
> xattr which complicates things.
>
> MingMing/Annesh -
> Xattr or other way to get at birth time?
>
>
Not yet,
The ext4 file creation time only accesable from the kernel at the moment.
There were discussion
to make this information avaliable via xattr before, but was rejected,
since most people
agree that making this info avalibele via stat() is more standard. However
modifying stat() would imply
big interface change. thus no action has been taken yet.
> --
> Thanks,
>
> Steve
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
2010-06-26 0:52 ` Mingming Cao
@ 2010-06-27 18:17 ` Aneesh Kumar K. V
[not found] ` <871vbscpce.fsf-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
0 siblings, 1 reply; 56+ messages in thread
From: Aneesh Kumar K. V @ 2010-06-27 18:17 UTC (permalink / raw)
To: Mingming Cao, Steve French, DENIEL Philippe
Cc: David Howells, Jeff Layton, Jeff Layton, linux-cifs,
linux-fsdevel, linux-kernel, samba-technical, Suresh Jayaraman
On Fri, 25 Jun 2010 17:52:24 -0700, Mingming Cao <mcao@us.ibm.com> wrote:
>
>
> Steve French <smfrench@gmail.com> wrote on 06/25/2010 04:05:30 PM:
>
> > Steve French <smfrench@gmail.com>
> > 06/25/2010 04:05 PM
> >
> > To
> >
> > Jeff Layton <jlayton@samba.org>, "Aneesh Kumar K.V"
> > <aneesh.kumar@linux.vnet.ibm.com>, Mingming Cao/Beaverton/IBM@IBMUS
> >
> > cc
> >
> > David Howells <dhowells@redhat.com>, Suresh Jayaraman
> > <sjayaraman@suse.de>, linux-cifs@vger.kernel.org, linux-
> > fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, samba-
> > technical@lists.samba.org, Jeff Layton <jlayton@redhat.com>
> >
> > Subject
> >
> > Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and
> > register them
> >
> > On Fri, Jun 25, 2010 at 5:26 PM, Jeff Layton <jlayton@samba.org> wrote:
> > >
> > > On Fri, 25 Jun 2010 22:46:38 +0100
> > > David Howells <dhowells@redhat.com> wrote:
> > >
> > > > Jeff Layton <jlayton@samba.org> wrote:
> > > >
> > > > > Looks like it mostly uses the ctime. IMO, the mtime would be a
> better
> > > > > choice since it changes less frequently, but I don't guess that it
> > > > > matters very much.
> > > >
> > > > I'd've thought mtime changes more frequently since that's
> > altered when data is
> > > > written. ctime is changed when attributes are changed.
> > > >
> > >
> > > IIUC, updating mtime for a write is also an attribute change, and that
> > > affects ctime. According to the stat(2) manpage:
> > >
> > > The field st_ctime is changed by writing or by setting
> > inode informa-
> > > tion (i.e., owner, group, link count, mode, etc.).
> > >
> > > > Note that Ext4 appears to have a file creation time field in its
> inode
> > > > (struct ext4_inode::i_crtime[_extra]). Can Samba be made to use
> that?
> > > >
> > >
> > > Is it exposed to userspace in any (standard) way? It would be handy to
> > > have that. While we're wishing...it might also be nice to have a
> > > standard way to get at the i_generation from userspace too.
> > >
> >
> > Yes - I have talked with MingMing and Aneesh about those (NFS may
> > someday be able to use those too). An obstacle in the past had been
> > that samba server stores its own fake creation time in an ndr encoded
> > xattr which complicates things.
> >
> > MingMing/Annesh -
> > Xattr or other way to get at birth time?
> >
> >
>
> Not yet,
> The ext4 file creation time only accesable from the kernel at the moment.
> There were discussion
> to make this information avaliable via xattr before, but was rejected,
> since most people
> agree that making this info avalibele via stat() is more standard. However
> modifying stat() would imply
> big interface change. thus no action has been taken yet.
NFS ganesha pNFS also had a requirement for getting i_generation and
inode number in userspace. So may be we should now look at updating
stat or add a variant syscall that include i_generation and create time
in the return value
-aneesh
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 06/10] cifs: define inode-level cache object and register them
[not found] ` <871vbscpce.fsf-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
@ 2010-06-27 18:22 ` Christoph Hellwig
0 siblings, 0 replies; 56+ messages in thread
From: Christoph Hellwig @ 2010-06-27 18:22 UTC (permalink / raw)
To: Aneesh Kumar K. V
Cc: Mingming Cao, Steve French, DENIEL Philippe, David Howells,
Jeff Layton, Jeff Layton, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
samba-technical-w/Ol4Ecudpl8XjKLYN78aQ, Suresh Jayaraman
On Sun, Jun 27, 2010 at 11:47:21PM +0530, Aneesh Kumar K. V wrote:
> NFS ganesha pNFS also had a requirement for getting i_generation and
> inode number in userspace. So may be we should now look at updating
> stat or add a variant syscall that include i_generation and create time
> in the return value
What's missing in knfsd that you feel the sudden urge to move backwards
to a userspace nfsd (one with a horribly crappy codebase, too).
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
[not found] ` <23204.1277472412-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-28 12:53 ` Suresh Jayaraman
0 siblings, 0 replies; 56+ messages in thread
From: Suresh Jayaraman @ 2010-06-28 12:53 UTC (permalink / raw)
To: David Howells
Cc: Steve French, linux-cifs-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
On 06/25/2010 06:56 PM, David Howells wrote:
> David Howells <dhowells-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>
>>>> validate the root directory of the share in some way?
>>>
>>> I don't know if there is a way to do this.
>>
>> Is there an inode number or something? Even the creation time might do.
>
> Looking in cifspdu.h, there are a number of things that it might be possible
> to use.
>
> (1) FILE_ALL_INFO: CreationTime, IndexNumber, IndexNumber1, FileName
> (assuming this isn't flattened to '\' or something for the root of a
> share.
>
> (2) FILE_UNIX_BASIC_INFO: DevMajor, DevMinor, UniqueId.
>
> (3) FILE_INFO_STANDARD: CreationDate, CreationTime.
>
> (4) FILE_INFO_BASIC: CreationTime.
>
> (5) FILE_DIRECTORY_INFO: FileIndex, CreationTime, FileName.
>
> (6) SEARCH_ID_FULL_DIR_INFO: FileIndex, CreationTime, UniqueId, FileName.
>
> (7) FILE_BOTH_DIRECTORY_INFO: FileIndex, CreationTime, ShortName, FileName.
>
> (8) OPEN_RSP_EXT: Fid, CreationTime, VolumeGUID, FileId.
>
> You may have to choose different sets of things, depending on what the server
> has on offer. Also, don't forget, if you can't work out whether a share is
Did you mean we need to validate differently for different servers?
I just did some testing and it looks like we could rely on CreationTime,
IndexNumber for validating with Windows servers (FileName is relative to
the mapped drive) and UniqueId for validating with Samba servers. I did
not test all possibilities (there could be more).
> coherent or not from the above, you can always use LastWriteTime, ChangeTime
> and EndOfFile and just discard the whole subtree if they differ.
>
Thanks,
--
Suresh Jayaraman
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them
2010-06-25 13:26 ` David Howells
[not found] ` <23204.1277472412-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2010-06-28 13:24 ` David Howells
1 sibling, 0 replies; 56+ messages in thread
From: David Howells @ 2010-06-28 13:24 UTC (permalink / raw)
To: Suresh Jayaraman
Cc: dhowells, Steve French, linux-cifs, linux-fsdevel, linux-kernel
Suresh Jayaraman <sjayaraman@suse.de> wrote:
> Did you mean we need to validate differently for different servers?
You may need to, yes, as different servers may make different attributes
available.
This isn't too bad. Each server index record in the cache has freeform
auxiliary data, just as does each file data record. You could, say, stick a
byte at the front that indicates what you've stored in there.
David
^ permalink raw reply [flat|nested] 56+ messages in thread
end of thread, other threads:[~2010-06-28 13:24 UTC | newest]
Thread overview: 56+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <yes>
2009-01-16 18:08 ` Quota fixes and improvements Jan Kara
2009-01-16 18:08 ` [PATCH 01/11] quota: Improve locking Jan Kara
2009-01-16 18:08 ` [PATCH 02/11] ocfs2: Remove ocfs2_dquot_initialize() and ocfs2_dquot_drop() Jan Kara
2009-01-16 18:08 ` [PATCH 03/11] ocfs2: Push out dropping of dentry lock to ocfs2_wq Jan Kara
2009-01-16 18:08 ` [PATCH 04/11] ocfs2: Fix possible deadlock in ocfs2_write_dquot() Jan Kara
2009-01-16 18:08 ` [PATCH 05/11] quota: Add quota reservation support Jan Kara
2009-01-16 18:08 ` [PATCH 06/11] quota: Add quota reservation claim and released operations Jan Kara
2009-01-16 18:08 ` [PATCH 07/11] quota: Use inode->i_blkbits to get block bits Jan Kara
2009-01-16 18:08 ` [PATCH 08/11] quota: Move EXPORT_SYMBOL immediately next to the functions/varibles Jan Kara
2009-01-16 18:08 ` [PATCH 09/11] ext3: Remove unnecessary quota functions Jan Kara
2009-01-16 18:08 ` [PATCH 10/11] ext4: " Jan Kara
2009-01-16 18:08 ` [PATCH 11/11] reiserfs: " Jan Kara
2009-01-20 21:41 ` [PATCH 10/11] ext4: " Mingming Cao
2009-01-20 21:41 ` [PATCH 09/11] ext3: " Mingming Cao
2009-01-24 7:49 ` [PATCH 01/11] quota: Improve locking Andrew Morton
2009-01-26 10:04 ` Jan Kara
2010-06-22 15:20 ` [RFC][PATCH 00/10] cifs: local caching support using FS-Cache Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 01/10] cifs: add kernel config option for CIFS Client caching support Suresh Jayaraman
2010-06-22 15:22 ` [RFC][PATCH 02/10] cifs: guard cifsglob.h against multiple inclusion Suresh Jayaraman
[not found] ` <1277220170-3442-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 21:37 ` Jeff Layton
2010-06-22 15:23 ` [RFC][PATCH 03/10] cifs: register CIFS for caching Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache Suresh Jayaraman
[not found] ` <1277220198-3522-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-22 21:52 ` Jeff Layton
[not found] ` <20100622175214.4c56234f-4QP7MXygkU+dMjc06nkz3ljfA9RmPOcC@public.gmane.org>
2010-06-23 5:34 ` Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " Suresh Jayaraman
2010-06-22 15:23 ` [RFC][PATCH 07/10] cifs: FS-Cache page management Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 08/10] cifs: store pages into local cache Suresh Jayaraman
2010-06-22 15:24 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache Suresh Jayaraman
2010-06-22 15:25 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching Suresh Jayaraman
2010-06-23 18:32 ` Scott Lovenberg
[not found] ` <4C225338.9010807-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2010-06-25 10:48 ` Suresh Jayaraman
[not found] ` <1277220189-3485-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 16:51 ` [RFC][PATCH 03/10] cifs: register CIFS for caching David Howells
[not found] ` <9603.1277311877-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 10:56 ` Suresh Jayaraman
2010-06-23 16:54 ` [RFC][PATCH 04/10] cifs: define server-level cache index objects and register them with FS-Cache David Howells
[not found] ` <1277220206-3559-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 16:58 ` [RFC][PATCH 05/10] cifs: define superblock-level cache index objects and register them David Howells
[not found] ` <9720.1277312290-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 12:44 ` Suresh Jayaraman
2010-06-25 12:58 ` David Howells
[not found] ` <22746.1277470713-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 13:26 ` David Howells
[not found] ` <23204.1277472412-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-28 12:53 ` Suresh Jayaraman
2010-06-28 13:24 ` David Howells
[not found] ` <1277220214-3597-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:02 ` [RFC][PATCH 06/10] cifs: define inode-level cache object " David Howells
[not found] ` <9822.1277312573-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 12:50 ` Suresh Jayaraman
[not found] ` <4C24A606.5040001-l3A5Bk7waGM@public.gmane.org>
2010-06-25 12:55 ` David Howells
[not found] ` <22697.1277470549-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2010-06-25 16:53 ` Jeff Layton
2010-06-25 21:46 ` David Howells
2010-06-25 22:26 ` Jeff Layton
2010-06-25 23:05 ` Steve French
2010-06-26 0:52 ` Mingming Cao
2010-06-27 18:17 ` Aneesh Kumar K. V
[not found] ` <871vbscpce.fsf-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
2010-06-27 18:22 ` Christoph Hellwig
[not found] ` <20100625182651.36800d06-9yPaYZwiELC+kQycOl6kW4xkIHaj4LzF@public.gmane.org>
2010-06-25 23:04 ` David Howells
2010-06-23 17:05 ` [RFC][PATCH 07/10] cifs: FS-Cache page management David Howells
[not found] ` <1277220240-3674-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:06 ` [RFC][PATCH 08/10] cifs: store pages into local cache David Howells
[not found] ` <1277220261-3717-1-git-send-email-sjayaraman-l3A5Bk7waGM@public.gmane.org>
2010-06-23 17:07 ` [RFC][PATCH 09/10] cifs: read pages from FS-Cache David Howells
2010-06-23 17:08 ` [RFC][PATCH 10/10] cifs: add mount option to enable local caching David Howells
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).