diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-08-19 18:13:00 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-08-19 18:22:16 -0400 |
commit | f7e86ab92f2198d30828a1a327ad2085e4a7ff7d (patch) | |
tree | d4bb64c7ae10c67c0292af6b1a2b7d1e25f19480 | |
parent | 7d7ea882898f23989209d0359691b356f73240dc (diff) |
SUNRPC: cache must take a reference to the cache detail's module on open()
Otherwise we Oops if the module containing the cache detail is removed
before all cache readers have closed the file.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | net/sunrpc/cache.c | 80 |
1 files changed, 76 insertions, 4 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index db7720e453c3..45cdaff9b361 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -836,6 +836,8 @@ static int cache_open(struct inode *inode, struct file *filp, | |||
836 | { | 836 | { |
837 | struct cache_reader *rp = NULL; | 837 | struct cache_reader *rp = NULL; |
838 | 838 | ||
839 | if (!cd || !try_module_get(cd->owner)) | ||
840 | return -EACCES; | ||
839 | nonseekable_open(inode, filp); | 841 | nonseekable_open(inode, filp); |
840 | if (filp->f_mode & FMODE_READ) { | 842 | if (filp->f_mode & FMODE_READ) { |
841 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 843 | rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
@@ -879,6 +881,7 @@ static int cache_release(struct inode *inode, struct file *filp, | |||
879 | cd->last_close = get_seconds(); | 881 | cd->last_close = get_seconds(); |
880 | atomic_dec(&cd->readers); | 882 | atomic_dec(&cd->readers); |
881 | } | 883 | } |
884 | module_put(cd->owner); | ||
882 | return 0; | 885 | return 0; |
883 | } | 886 | } |
884 | 887 | ||
@@ -1215,6 +1218,8 @@ static int content_open(struct inode *inode, struct file *file, | |||
1215 | { | 1218 | { |
1216 | struct handle *han; | 1219 | struct handle *han; |
1217 | 1220 | ||
1221 | if (!cd || !try_module_get(cd->owner)) | ||
1222 | return -EACCES; | ||
1218 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); | 1223 | han = __seq_open_private(file, &cache_content_op, sizeof(*han)); |
1219 | if (han == NULL) | 1224 | if (han == NULL) |
1220 | return -ENOMEM; | 1225 | return -ENOMEM; |
@@ -1223,6 +1228,29 @@ static int content_open(struct inode *inode, struct file *file, | |||
1223 | return 0; | 1228 | return 0; |
1224 | } | 1229 | } |
1225 | 1230 | ||
1231 | static int content_release(struct inode *inode, struct file *file, | ||
1232 | struct cache_detail *cd) | ||
1233 | { | ||
1234 | int ret = seq_release_private(inode, file); | ||
1235 | module_put(cd->owner); | ||
1236 | return ret; | ||
1237 | } | ||
1238 | |||
1239 | static int open_flush(struct inode *inode, struct file *file, | ||
1240 | struct cache_detail *cd) | ||
1241 | { | ||
1242 | if (!cd || !try_module_get(cd->owner)) | ||
1243 | return -EACCES; | ||
1244 | return nonseekable_open(inode, file); | ||
1245 | } | ||
1246 | |||
1247 | static int release_flush(struct inode *inode, struct file *file, | ||
1248 | struct cache_detail *cd) | ||
1249 | { | ||
1250 | module_put(cd->owner); | ||
1251 | return 0; | ||
1252 | } | ||
1253 | |||
1226 | static ssize_t read_flush(struct file *file, char __user *buf, | 1254 | static ssize_t read_flush(struct file *file, char __user *buf, |
1227 | size_t count, loff_t *ppos, | 1255 | size_t count, loff_t *ppos, |
1228 | struct cache_detail *cd) | 1256 | struct cache_detail *cd) |
@@ -1331,13 +1359,34 @@ static int content_open_procfs(struct inode *inode, struct file *filp) | |||
1331 | return content_open(inode, filp, cd); | 1359 | return content_open(inode, filp, cd); |
1332 | } | 1360 | } |
1333 | 1361 | ||
1362 | static int content_release_procfs(struct inode *inode, struct file *filp) | ||
1363 | { | ||
1364 | struct cache_detail *cd = PDE(inode)->data; | ||
1365 | |||
1366 | return content_release(inode, filp, cd); | ||
1367 | } | ||
1368 | |||
1334 | static const struct file_operations content_file_operations_procfs = { | 1369 | static const struct file_operations content_file_operations_procfs = { |
1335 | .open = content_open_procfs, | 1370 | .open = content_open_procfs, |
1336 | .read = seq_read, | 1371 | .read = seq_read, |
1337 | .llseek = seq_lseek, | 1372 | .llseek = seq_lseek, |
1338 | .release = seq_release_private, | 1373 | .release = content_release_procfs, |
1339 | }; | 1374 | }; |
1340 | 1375 | ||
1376 | static int open_flush_procfs(struct inode *inode, struct file *filp) | ||
1377 | { | ||
1378 | struct cache_detail *cd = PDE(inode)->data; | ||
1379 | |||
1380 | return open_flush(inode, filp, cd); | ||
1381 | } | ||
1382 | |||
1383 | static int release_flush_procfs(struct inode *inode, struct file *filp) | ||
1384 | { | ||
1385 | struct cache_detail *cd = PDE(inode)->data; | ||
1386 | |||
1387 | return release_flush(inode, filp, cd); | ||
1388 | } | ||
1389 | |||
1341 | static ssize_t read_flush_procfs(struct file *filp, char __user *buf, | 1390 | static ssize_t read_flush_procfs(struct file *filp, char __user *buf, |
1342 | size_t count, loff_t *ppos) | 1391 | size_t count, loff_t *ppos) |
1343 | { | 1392 | { |
@@ -1356,9 +1405,10 @@ static ssize_t write_flush_procfs(struct file *filp, | |||
1356 | } | 1405 | } |
1357 | 1406 | ||
1358 | static const struct file_operations cache_flush_operations_procfs = { | 1407 | static const struct file_operations cache_flush_operations_procfs = { |
1359 | .open = nonseekable_open, | 1408 | .open = open_flush_procfs, |
1360 | .read = read_flush_procfs, | 1409 | .read = read_flush_procfs, |
1361 | .write = write_flush_procfs, | 1410 | .write = write_flush_procfs, |
1411 | .release = release_flush_procfs, | ||
1362 | }; | 1412 | }; |
1363 | 1413 | ||
1364 | static void remove_cache_proc_entries(struct cache_detail *cd) | 1414 | static void remove_cache_proc_entries(struct cache_detail *cd) |
@@ -1503,13 +1553,34 @@ static int content_open_pipefs(struct inode *inode, struct file *filp) | |||
1503 | return content_open(inode, filp, cd); | 1553 | return content_open(inode, filp, cd); |
1504 | } | 1554 | } |
1505 | 1555 | ||
1556 | static int content_release_pipefs(struct inode *inode, struct file *filp) | ||
1557 | { | ||
1558 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1559 | |||
1560 | return content_release(inode, filp, cd); | ||
1561 | } | ||
1562 | |||
1506 | const struct file_operations content_file_operations_pipefs = { | 1563 | const struct file_operations content_file_operations_pipefs = { |
1507 | .open = content_open_pipefs, | 1564 | .open = content_open_pipefs, |
1508 | .read = seq_read, | 1565 | .read = seq_read, |
1509 | .llseek = seq_lseek, | 1566 | .llseek = seq_lseek, |
1510 | .release = seq_release_private, | 1567 | .release = content_release_pipefs, |
1511 | }; | 1568 | }; |
1512 | 1569 | ||
1570 | static int open_flush_pipefs(struct inode *inode, struct file *filp) | ||
1571 | { | ||
1572 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1573 | |||
1574 | return open_flush(inode, filp, cd); | ||
1575 | } | ||
1576 | |||
1577 | static int release_flush_pipefs(struct inode *inode, struct file *filp) | ||
1578 | { | ||
1579 | struct cache_detail *cd = RPC_I(inode)->private; | ||
1580 | |||
1581 | return release_flush(inode, filp, cd); | ||
1582 | } | ||
1583 | |||
1513 | static ssize_t read_flush_pipefs(struct file *filp, char __user *buf, | 1584 | static ssize_t read_flush_pipefs(struct file *filp, char __user *buf, |
1514 | size_t count, loff_t *ppos) | 1585 | size_t count, loff_t *ppos) |
1515 | { | 1586 | { |
@@ -1528,9 +1599,10 @@ static ssize_t write_flush_pipefs(struct file *filp, | |||
1528 | } | 1599 | } |
1529 | 1600 | ||
1530 | const struct file_operations cache_flush_operations_pipefs = { | 1601 | const struct file_operations cache_flush_operations_pipefs = { |
1531 | .open = nonseekable_open, | 1602 | .open = open_flush_pipefs, |
1532 | .read = read_flush_pipefs, | 1603 | .read = read_flush_pipefs, |
1533 | .write = write_flush_pipefs, | 1604 | .write = write_flush_pipefs, |
1605 | .release = release_flush_pipefs, | ||
1534 | }; | 1606 | }; |
1535 | 1607 | ||
1536 | int sunrpc_cache_register_pipefs(struct dentry *parent, | 1608 | int sunrpc_cache_register_pipefs(struct dentry *parent, |