diff --git a/lustre/include/linux/lprocfs_status.h b/lustre/include/linux/lprocfs_status.h index 8fbbe6199a46724f15cbea8aaa0b40b63cc5c168..3f4d52fefc21f28f20e63aefa895b7a8a57721b7 100644 --- a/lustre/include/linux/lprocfs_status.h +++ b/lustre/include/linux/lprocfs_status.h @@ -256,9 +256,11 @@ extern int lprocfs_rd_filesfree(char *page, char **start, off_t off, extern int lprocfs_rd_filegroups(char *page, char **start, off_t off, int count, int *eof, void *data); -extern int lprocfs_write_helper(const char *buffer, unsigned long count, +extern int lprocfs_write_helper(const char *buffer, unsigned long count, int *val); -int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode, +extern int lprocfs_write_u64_helper(const char *buffer, unsigned long count, + __u64 *val); +int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode, struct file_operations *seq_fops, void *data); struct obd_histogram; void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value); diff --git a/lustre/include/linux/obd.h b/lustre/include/linux/obd.h index 3982a4ce4b1033167de9148c0e4e331a2c8e0f62..d946942b40404e0ebed6fee590e1de1dc0dd6b10 100644 --- a/lustre/include/linux/obd.h +++ b/lustre/include/linux/obd.h @@ -168,6 +168,8 @@ struct filter_obd { obd_size fo_tot_granted; obd_size fo_tot_cached; + obd_size fo_readcache_max_filesize; + struct obd_import *fo_mdc_imp; struct obd_uuid fo_mdc_uuid; struct lustre_handle fo_mdc_conn; diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index a5ad77c6690337a9985068f30b07d207fc35a88f..eb982516330a2fee7ae20ba075d0d58c437d8edc 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -684,7 +684,27 @@ int lprocfs_write_helper(const char *buffer, unsigned long count, return 0; } -int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode, +int lprocfs_write_u64_helper(const char *buffer, unsigned long count, + __u64 *val) +{ + char kernbuf[22], *end; + + if (count > (sizeof(kernbuf) - 1)) + return -EINVAL; + + if (copy_from_user(kernbuf, buffer, count)) + return -EFAULT; + + kernbuf[count] = '\0'; + + *val = simple_strtoull(kernbuf, &end, 0); + if (kernbuf == end) + return -EINVAL; + + return 0; +} + +int lprocfs_obd_seq_create(struct obd_device *dev, char *name, mode_t mode, struct file_operations *seq_fops, void *data) { struct proc_dir_entry *entry; @@ -774,3 +794,4 @@ EXPORT_SYMBOL(lprocfs_rd_filesfree); EXPORT_SYMBOL(lprocfs_rd_filegroups); EXPORT_SYMBOL(lprocfs_write_helper); +EXPORT_SYMBOL(lprocfs_write_u64_helper); diff --git a/lustre/obdfilter/filter.c b/lustre/obdfilter/filter.c index 86eda2d1ca485b9cff6ee880e74d5ea43671b28a..93d363ed1d32416ceb1dcc928acffce056ad8362 100644 --- a/lustre/obdfilter/filter.c +++ b/lustre/obdfilter/filter.c @@ -1123,6 +1123,7 @@ int filter_common_setup(struct obd_device *obd, obd_count len, void *buf, spin_lock_init(&filter->fo_w_discont_pages.oh_lock); spin_lock_init(&filter->fo_r_discont_blocks.oh_lock); spin_lock_init(&filter->fo_w_discont_blocks.oh_lock); + filter->fo_readcache_max_filesize = FILTER_MAX_CACHE_SIZE; obd->obd_namespace = ldlm_namespace_new("filter-tgt", LDLM_NAMESPACE_SERVER); diff --git a/lustre/obdfilter/filter_internal.h b/lustre/obdfilter/filter_internal.h index 610d969c0b4ffdb751efa12da0510a263276ca7a..ce7b4a372ba9143cd36f73755e4dbe3d861df656 100644 --- a/lustre/obdfilter/filter_internal.h +++ b/lustre/obdfilter/filter_internal.h @@ -90,6 +90,8 @@ enum { LPROC_FILTER_LAST, }; +#define FILTER_MAX_CACHE_SIZE OBD_OBJECT_EOF + /* filter.c */ struct dentry *filter_parent(struct obd_device *, obd_gr group, obd_id objid); struct dentry *filter_parent_lock(struct obd_device *, obd_gr, obd_id, diff --git a/lustre/obdfilter/filter_io.c b/lustre/obdfilter/filter_io.c index 774e669200276b9b755ee058d97d5e79f7ce6dee..afb49dbb20863705c64666f84a8efa00a908d248 100644 --- a/lustre/obdfilter/filter_io.c +++ b/lustre/obdfilter/filter_io.c @@ -360,13 +360,24 @@ static int filter_commitrw_read(struct obd_export *exp, struct obdo *oa, { struct obd_ioobj *o; struct niobuf_local *lnb; - int i, j; + int i, j, drop = 0; ENTRY; + if (res->dentry != NULL) + drop = (res->dentry->d_inode->i_size > + exp->exp_obd->u.filter.fo_readcache_max_filesize); + for (i = 0, o = obj, lnb = res; i < objcount; i++, o++) { for (j = 0 ; j < o->ioo_bufcnt ; j++, lnb++) { - if (lnb->page != NULL) - page_cache_release(lnb->page); + if (lnb->page == NULL) + continue; + /* drop from cache like truncate_list_pages() */ + if (drop && !TryLockPage(lnb->page)) { + if (lnb->page->mapping) + truncate_complete_page(lnb->page); + unlock_page(lnb->page); + } + page_cache_release(lnb->page); } } if (res->dentry != NULL) diff --git a/lustre/obdfilter/lproc_obdfilter.c b/lustre/obdfilter/lproc_obdfilter.c index 77f085276c3a23595243b611aa3119aa8393d81a..51458c0a8b138e524247945f2a7da858b73f04fc 100644 --- a/lustre/obdfilter/lproc_obdfilter.c +++ b/lustre/obdfilter/lproc_obdfilter.c @@ -58,6 +58,32 @@ static int lprocfs_filter_rd_last_id(char *page, char **start, off_t off, filter_last_id(&obd->u.filter, 0)); } +int lprocfs_filter_rd_readcache(char *page, char **start, off_t off, int count, + int *eof, void *data) +{ + struct obd_device *obd = data; + int rc; + + rc = snprintf(page, count, LPU64"\n", + obd->u.filter.fo_readcache_max_filesize); + return rc; +} + +int lprocfs_filter_wr_readcache(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + struct obd_device *obd = data; + __u64 val; + int rc; + + rc = lprocfs_write_u64_helper(buffer, count, &val); + if (rc) + return rc; + + obd->u.filter.fo_readcache_max_filesize = val; + return count; +} + static struct lprocfs_vars lprocfs_obd_vars[] = { { "uuid", lprocfs_rd_uuid, 0, 0 }, { "blocksize", lprocfs_rd_blksize, 0, 0 }, @@ -68,7 +94,10 @@ static struct lprocfs_vars lprocfs_obd_vars[] = { //{ "filegroups", lprocfs_rd_filegroups, 0, 0 }, { "fstype", lprocfs_rd_fstype, 0, 0 }, { "mntdev", lprocfs_filter_rd_mntdev, 0, 0 }, - { "last_id", lprocfs_filter_rd_last_id, 0, 0 }, + { "last_id", lprocfs_filter_rd_last_id,0, 0 }, + { "readcache_max_filesize", + lprocfs_filter_rd_readcache, + lprocfs_filter_wr_readcache, 0 }, { 0 } };