Pull fsnotify updates from Jan Kara: "A few fsnotify fixes from Amir fixing fallout from big fsnotify overhaul a few months back and an improvement of defaults limiting maximum number of inotify watches from Waiman" * tag 'fsnotify_for_v5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: fsnotify: fix events reported to watching parent and child inotify: convert to handle_inode_event() interface fsnotify: generalize handle_inode_event() inotify: Increase default inotify.max_user_watches limit to 1048576
Unified · Split
| @@ -600,7 +600,7 @@ static struct notifier_block nfsd_file_lease_notifier = { · 599 unmodified lines | |||
| 600 | static int | 600 | static int |
| 601 | nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask, | 601 | nfsd_file_fsnotify_handle_event(struct fsnotify_mark *mark, u32 mask, |
| 602 | struct inode *inode, struct inode *dir, | 602 | struct inode *inode, struct inode *dir, |
| 603 | const struct qstr *name) | 603 | const struct qstr *name, u32 cookie) |
| 604 | { | 604 | { |
| 605 | trace_nfsd_file_fsnotify_handle_event(inode, mask); | 605 | trace_nfsd_file_fsnotify_handle_event(inode, mask); |
| 606 | 606 | ||
| @@ -72,7 +72,7 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark) · 71 unmodified lines | |||
| 72 | */ | 72 | */ |
| 73 | static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask, | 73 | static int dnotify_handle_event(struct fsnotify_mark *inode_mark, u32 mask, |
| 74 | struct inode *inode, struct inode *dir, | 74 | struct inode *inode, struct inode *dir, |
| 75 | const struct qstr *name) | 75 | const struct qstr *name, u32 cookie) |
| 76 | { | 76 | { |
| 77 | struct dnotify_mark *dn_mark; | 77 | struct dnotify_mark *dn_mark; |
| 78 | struct dnotify_struct *dn; | 78 | struct dnotify_struct *dn; |
| @@ -268,12 +268,11 @@ static u32 fanotify_group_event_mask(struct fsnotify_group *group, · 267 unmodified lines | |||
| 268 | continue; | 268 | continue; |
| 269 | 269 | ||
| 270 | /* | 270 | /* |
| 271 | * If the event is for a child and this mark is on a parent not | 271 | * If the event is on a child and this mark is on a parent not |
| 272 | * watching children, don't send it! | 272 | * watching children, don't send it! |
| 273 | */ | 273 | */ |
| 274 | if (event_mask & FS_EVENT_ON_CHILD && | 274 | if (type == FSNOTIFY_OBJ_TYPE_PARENT && |
| 275 | type == FSNOTIFY_OBJ_TYPE_INODE && | 275 | !(mark->mask & FS_EVENT_ON_CHILD)) |
| 276 | !(mark->mask & FS_EVENT_ON_CHILD)) | ||
| 277 | continue; | 276 | continue; |
| 278 | 277 | ||
| 279 | marks_mask |= mark->mask; | 278 | marks_mask |= mark->mask; |
| @@ -152,6 +152,13 @@ static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt, · 151 unmodified lines | |||
| 152 | if (mask & FS_ISDIR) | 152 | if (mask & FS_ISDIR) |
| 153 | return false; | 153 | return false; |
| 154 | 154 | ||
| 155 | /* | ||
| 156 | * All events that are possible on child can also may be reported with | ||
| 157 | * parent/name info to inode/sb/mount. Otherwise, a watching parent | ||
| 158 | * could result in events reported with unexpected name info to sb/mount. | ||
| 159 | */ | ||
| 160 | BUILD_BUG_ON(FS_EVENTS_POSS_ON_CHILD & ~FS_EVENTS_POSS_TO_PARENT); | ||
| 161 | |||
| 155 | /* Did either inode/sb/mount subscribe for events with parent/name? */ | 162 | /* Did either inode/sb/mount subscribe for events with parent/name? */ |
| 156 | marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask); | 163 | marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask); |
| 157 | marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); | 164 | marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); |
| @@ -232,47 +239,76 @@ notify: · 74 unmodified lines | |||
| 232 | } | 239 | } |
| 233 | EXPORT_SYMBOL_GPL(__fsnotify_parent); | 240 | EXPORT_SYMBOL_GPL(__fsnotify_parent); |
| 234 | 241 | ||
| 242 | static int fsnotify_handle_inode_event(struct fsnotify_group *group, | ||
| 243 | struct fsnotify_mark *inode_mark, | ||
| 244 | u32 mask, const void *data, int data_type, | ||
| 245 | struct inode *dir, const struct qstr *name, | ||
| 246 | u32 cookie) | ||
| 247 | { | ||
| 248 | const struct path *path = fsnotify_data_path(data, data_type); | ||
| 249 | struct inode *inode = fsnotify_data_inode(data, data_type); | ||
| 250 | const struct fsnotify_ops *ops = group->ops; | ||
| 251 | |||
| 252 | if (WARN_ON_ONCE(!ops->handle_inode_event)) | ||
| 253 | return 0; | ||
| 254 | |||
| 255 | if ((inode_mark->mask & FS_EXCL_UNLINK) && | ||
| 256 | path && d_unlinked(path->dentry)) | ||
| 257 | return 0; | ||
| 258 | |||
| 259 | /* Check interest of this mark in case event was sent with two marks */ | ||
| 260 | if (!(mask & inode_mark->mask & ALL_FSNOTIFY_EVENTS)) | ||
| 261 | return 0; | ||
| 262 | |||
| 263 | return ops->handle_inode_event(inode_mark, mask, inode, dir, name, cookie); | ||
| 264 | } | ||
| 265 | |||
| 235 | static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, | 266 | static int fsnotify_handle_event(struct fsnotify_group *group, __u32 mask, |
| 236 | const void *data, int data_type, | 267 | const void *data, int data_type, |
| 237 | struct inode *dir, const struct qstr *name, | 268 | struct inode *dir, const struct qstr *name, |
| 238 | u32 cookie, struct fsnotify_iter_info *iter_info) | 269 | u32 cookie, struct fsnotify_iter_info *iter_info) |
| 239 | { | 270 | { |
| 240 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | 271 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); |
| 241 | struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); | 272 | struct fsnotify_mark *parent_mark = fsnotify_iter_parent_mark(iter_info); |
| 242 | struct inode *inode = fsnotify_data_inode(data, data_type); | ||
| 243 | const struct fsnotify_ops *ops = group->ops; | ||
| 244 | int ret; | 273 | int ret; |
| 245 | 274 | ||
| 246 | if (WARN_ON_ONCE(!ops->handle_inode_event)) | ||
| 247 | return 0; | ||
| 248 | |||
| 249 | if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) || | 275 | if (WARN_ON_ONCE(fsnotify_iter_sb_mark(iter_info)) || |
| 250 | WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info))) | 276 | WARN_ON_ONCE(fsnotify_iter_vfsmount_mark(iter_info))) |
| 251 | return 0; | 277 | return 0; |
| 252 | 278 | ||
| 253 | /* | 279 | if (parent_mark) { |
| 254 | * An event can be sent on child mark iterator instead of inode mark | 280 | /* |
| 255 | * iterator because of other groups that have interest of this inode | 281 | * parent_mark indicates that the parent inode is watching |
| 256 | * and have marks on both parent and child. We can simplify this case. | 282 | * children and interested in this event, which is an event |
| 257 | */ | 283 | * possible on child. But is *this mark* watching children and |
| 258 | if (!inode_mark) { | 284 | * interested in this event? |
| 259 | inode_mark = child_mark; | 285 | */ |
| 260 | child_mark = NULL; | 286 | if (parent_mark->mask & FS_EVENT_ON_CHILD) { |
| 287 | ret = fsnotify_handle_inode_event(group, parent_mark, mask, | ||
| 288 | data, data_type, dir, name, 0); | ||
| 289 | if (ret) | ||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | if (!inode_mark) | ||
| 293 | return 0; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (mask & FS_EVENT_ON_CHILD) { | ||
| 297 | /* | ||
| 298 | * Some events can be sent on both parent dir and child marks | ||
| 299 | * (e.g. FS_ATTRIB). If both parent dir and child are | ||
| 300 | * watching, report the event once to parent dir with name (if | ||
| 301 | * interested) and once to child without name (if interested). | ||
| 302 | * The child watcher is expecting an event without a file name | ||
| 303 | * and without the FS_EVENT_ON_CHILD flag. | ||
| 304 | */ | ||
| 305 | mask &= ~FS_EVENT_ON_CHILD; | ||
| 261 | dir = NULL; | 306 | dir = NULL; |
| 262 | name = NULL; | 307 | name = NULL; |
| 263 | } | 308 | } |
| 264 | 309 | ||
| 265 | ret = ops->handle_inode_event(inode_mark, mask, inode, dir, name); | 310 | return fsnotify_handle_inode_event(group, inode_mark, mask, data, data_type, |
| 266 | if (ret || !child_mark) | 311 | dir, name, cookie); |
| 267 | return ret; | ||
| 268 | |||
| 269 | /* | ||
| 270 | * Some events can be sent on both parent dir and child marks | ||
| 271 | * (e.g. FS_ATTRIB). If both parent dir and child are watching, | ||
| 272 | * report the event once to parent dir with name and once to child | ||
| 273 | * without name. | ||
| 274 | */ | ||
| 275 | return ops->handle_inode_event(child_mark, mask, inode, NULL, NULL); | ||
| 276 | } | 312 | } |
| 277 | 313 | ||
| 278 | static int send_to_group(__u32 mask, const void *data, int data_type, | 314 | static int send_to_group(__u32 mask, const void *data, int data_type, |
| @@ -430,7 +466,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 151 unmodified lines | |||
| 430 | struct fsnotify_iter_info iter_info = {}; | 466 | struct fsnotify_iter_info iter_info = {}; |
| 431 | struct super_block *sb; | 467 | struct super_block *sb; |
| 432 | struct mount *mnt = NULL; | 468 | struct mount *mnt = NULL; |
| 433 | struct inode *child = NULL; | 469 | struct inode *parent = NULL; |
| 434 | int ret = 0; | 470 | int ret = 0; |
| 435 | __u32 test_mask, marks_mask; | 471 | __u32 test_mask, marks_mask; |
| 436 | 472 | ||
| @@ -442,11 +478,10 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 5 unmodified lines | |||
| 442 | inode = dir; | 478 | inode = dir; |
| 443 | } else if (mask & FS_EVENT_ON_CHILD) { | 479 | } else if (mask & FS_EVENT_ON_CHILD) { |
| 444 | /* | 480 | /* |
| 445 | * Event on child - report on TYPE_INODE to dir if it is | 481 | * Event on child - report on TYPE_PARENT to dir if it is |
| 446 | * watching children and on TYPE_CHILD to child. | 482 | * watching children and on TYPE_INODE to child. |
| 447 | */ | 483 | */ |
| 448 | child = inode; | 484 | parent = dir; |
| 449 | inode = dir; | ||
| 450 | } | 485 | } |
| 451 | sb = inode->i_sb; | 486 | sb = inode->i_sb; |
| 452 | 487 | ||
| @@ -460,7 +495,7 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 7 unmodified lines | |||
| 460 | if (!sb->s_fsnotify_marks && | 495 | if (!sb->s_fsnotify_marks && |
| 461 | (!mnt || !mnt->mnt_fsnotify_marks) && | 496 | (!mnt || !mnt->mnt_fsnotify_marks) && |
| 462 | (!inode || !inode->i_fsnotify_marks) && | 497 | (!inode || !inode->i_fsnotify_marks) && |
| 463 | (!child || !child->i_fsnotify_marks)) | 498 | (!parent || !parent->i_fsnotify_marks)) |
| 464 | return 0; | 499 | return 0; |
| 465 | 500 | ||
| 466 | marks_mask = sb->s_fsnotify_mask; | 501 | marks_mask = sb->s_fsnotify_mask; |
| @@ -468,8 +503,8 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 1 unmodified line | |||
| 468 | marks_mask |= mnt->mnt_fsnotify_mask; | 503 | marks_mask |= mnt->mnt_fsnotify_mask; |
| 469 | if (inode) | 504 | if (inode) |
| 470 | marks_mask |= inode->i_fsnotify_mask; | 505 | marks_mask |= inode->i_fsnotify_mask; |
| 471 | if (child) | 506 | if (parent) |
| 472 | marks_mask |= child->i_fsnotify_mask; | 507 | marks_mask |= parent->i_fsnotify_mask; |
| 473 | 508 | ||
| 474 | 509 | ||
| 475 | /* | 510 | /* |
| @@ -492,9 +527,9 @@ int fsnotify(__u32 mask, const void *data, int data_type, struct inode *dir, · 16 unmodified lines | |||
| 492 | iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = | 527 | iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] = |
| 493 | fsnotify_first_mark(&inode->i_fsnotify_marks); | 528 | fsnotify_first_mark(&inode->i_fsnotify_marks); |
| 494 | } | 529 | } |
| 495 | if (child) { | 530 | if (parent) { |
| 496 | iter_info.marks[FSNOTIFY_OBJ_TYPE_CHILD] = | 531 | iter_info.marks[FSNOTIFY_OBJ_TYPE_PARENT] = |
| 497 | fsnotify_first_mark(&child->i_fsnotify_marks); | 532 | fsnotify_first_mark(&parent->i_fsnotify_marks); |
| 498 | } | 533 | } |
| 499 | 534 | ||
| 500 | /* | 535 | /* |
| @@ -24,11 +24,10 @@ static inline struct inotify_event_info *INOTIFY_E(struct fsnotify_event *fse) · 23 unmodified lines | |||
| 24 | 24 | ||
| 25 | extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, | 25 | extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, |
| 26 | struct fsnotify_group *group); | 26 | struct fsnotify_group *group); |
| 27 | extern int inotify_handle_event(struct fsnotify_group *group, u32 mask, | 27 | extern int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, |
| 28 | const void *data, int data_type, | 28 | u32 mask, struct inode *inode, |
| 29 | struct inode *dir, | 29 | struct inode *dir, |
| 30 | const struct qstr *file_name, u32 cookie, | 30 | const struct qstr *name, u32 cookie); |
| 31 | struct fsnotify_iter_info *iter_info); | ||
| 32 | 31 | ||
| 33 | extern const struct fsnotify_ops inotify_fsnotify_ops; | 32 | extern const struct fsnotify_ops inotify_fsnotify_ops; |
| 34 | extern struct kmem_cache *inotify_inode_mark_cachep; | 33 | extern struct kmem_cache *inotify_inode_mark_cachep; |
| @@ -55,25 +55,21 @@ static int inotify_merge(struct list_head *list, · 54 unmodified lines | |||
| 55 | return event_compare(last_event, event); | 55 | return event_compare(last_event, event); |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | static int inotify_one_event(struct fsnotify_group *group, u32 mask, | 58 | int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask, |
| 59 | struct fsnotify_mark *inode_mark, | 59 | struct inode *inode, struct inode *dir, |
| 60 | const struct path *path, | 60 | const struct qstr *name, u32 cookie) |
| 61 | const struct qstr *file_name, u32 cookie) | ||
| 62 | { | 61 | { |
| 63 | struct inotify_inode_mark *i_mark; | 62 | struct inotify_inode_mark *i_mark; |
| 64 | struct inotify_event_info *event; | 63 | struct inotify_event_info *event; |
| 65 | struct fsnotify_event *fsn_event; | 64 | struct fsnotify_event *fsn_event; |
| 65 | struct fsnotify_group *group = inode_mark->group; | ||
| 66 | int ret; | 66 | int ret; |
| 67 | int len = 0; | 67 | int len = 0; |
| 68 | int alloc_len = sizeof(struct inotify_event_info); | 68 | int alloc_len = sizeof(struct inotify_event_info); |
| 69 | struct mem_cgroup *old_memcg; | 69 | struct mem_cgroup *old_memcg; |
| 70 | 70 | ||
| 71 | if ((inode_mark->mask & FS_EXCL_UNLINK) && | 71 | if (name) { |
| 72 | path && d_unlinked(path->dentry)) | 72 | len = name->len; |
| 73 | return 0; | ||
| 74 | |||
| 75 | if (file_name) { | ||
| 76 | len = file_name->len; | ||
| 77 | alloc_len += len + 1; | 73 | alloc_len += len + 1; |
| 78 | } | 74 | } |
| 79 | 75 | ||
| @@ -117,7 +113,7 @@ static int inotify_one_event(struct fsnotify_group *group, u32 mask, · 37 unmodified lines | |||
| 117 | event->sync_cookie = cookie; | 113 | event->sync_cookie = cookie; |
| 118 | event->name_len = len; | 114 | event->name_len = len; |
| 119 | if (len) | 115 | if (len) |
| 120 | strcpy(event->name, file_name->name); | 116 | strcpy(event->name, name->name); |
| 121 | 117 | ||
| 122 | ret = fsnotify_add_event(group, fsn_event, inotify_merge); | 118 | ret = fsnotify_add_event(group, fsn_event, inotify_merge); |
| 123 | if (ret) { | 119 | if (ret) { |
| @@ -131,37 +127,6 @@ static int inotify_one_event(struct fsnotify_group *group, u32 mask, · 7 unmodified lines | |||
| 131 | return 0; | 127 | return 0; |
| 132 | } | 128 | } |
| 133 | 129 | ||
| 134 | int inotify_handle_event(struct fsnotify_group *group, u32 mask, | ||
| 135 | const void *data, int data_type, struct inode *dir, | ||
| 136 | const struct qstr *file_name, u32 cookie, | ||
| 137 | struct fsnotify_iter_info *iter_info) | ||
| 138 | { | ||
| 139 | const struct path *path = fsnotify_data_path(data, data_type); | ||
| 140 | struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info); | ||
| 141 | struct fsnotify_mark *child_mark = fsnotify_iter_child_mark(iter_info); | ||
| 142 | int ret = 0; | ||
| 143 | |||
| 144 | if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info))) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Some events cannot be sent on both parent and child marks | ||
| 149 | * (e.g. IN_CREATE). Those events are always sent on inode_mark. | ||
| 150 | * For events that are possible on both parent and child (e.g. IN_OPEN), | ||
| 151 | * event is sent on inode_mark with name if the parent is watching and | ||
| 152 | * is sent on child_mark without name if child is watching. | ||
| 153 | * If both parent and child are watching, report the event with child's | ||
| 154 | * name here and report another event without child's name below. | ||
| 155 | */ | ||
| 156 | if (inode_mark) | ||
| 157 | ret = inotify_one_event(group, mask, inode_mark, path, | ||
| 158 | file_name, cookie); | ||
| 159 | if (ret || !child_mark) | ||
| 160 | return ret; | ||
| 161 | |||
| 162 | return inotify_one_event(group, mask, child_mark, path, NULL, 0); | ||
| 163 | } | ||
| 164 | |||
| 165 | static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group) | 130 | static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group) |
| 166 | { | 131 | { |
| 167 | inotify_ignored_and_remove_idr(fsn_mark, group); | 132 | inotify_ignored_and_remove_idr(fsn_mark, group); |
| @@ -227,7 +192,7 @@ static void inotify_free_mark(struct fsnotify_mark *fsn_mark) · 59 unmodified lines | |||
| 227 | } | 192 | } |
| 228 | 193 | ||
| 229 | const struct fsnotify_ops inotify_fsnotify_ops = { | 194 | const struct fsnotify_ops inotify_fsnotify_ops = { |
| 230 | .handle_event = inotify_handle_event, | 195 | .handle_inode_event = inotify_handle_inode_event, |
| 231 | .free_group_priv = inotify_free_group_priv, | 196 | .free_group_priv = inotify_free_group_priv, |
| 232 | .free_event = inotify_free_event, | 197 | .free_event = inotify_free_event, |
| 233 | .freeing_mark = inotify_freeing_mark, | 198 | .freeing_mark = inotify_freeing_mark, |
| @@ -37,6 +37,15 @@ · 36 unmodified lines | |||
| 37 | 37 | ||
| 38 | #include <asm/ioctls.h> | 38 | #include <asm/ioctls.h> |
| 39 | 39 | ||
| 40 | /* | ||
| 41 | * An inotify watch requires allocating an inotify_inode_mark structure as | ||
| 42 | * well as pinning the watched inode. Doubling the size of a VFS inode | ||
| 43 | * should be more than enough to cover the additional filesystem inode | ||
| 44 | * size increase. | ||
| 45 | */ | ||
| 46 | #define INOTIFY_WATCH_COST (sizeof(struct inotify_inode_mark) + \ | ||
| 47 | 2 * sizeof(struct inode)) | ||
| 48 | |||
| 40 | /* configurable via /proc/sys/fs/inotify/ */ | 49 | /* configurable via /proc/sys/fs/inotify/ */ |
| 41 | static int inotify_max_queued_events __read_mostly; | 50 | static int inotify_max_queued_events __read_mostly; |
| 42 | 51 | ||
| @@ -486,14 +495,10 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark, · 443 unmodified lines | |||
| 486 | struct fsnotify_group *group) | 495 | struct fsnotify_group *group) |
| 487 | { | 496 | { |
| 488 | struct inotify_inode_mark *i_mark; | 497 | struct inotify_inode_mark *i_mark; |
| 489 | struct fsnotify_iter_info iter_info = { }; | ||
| 490 | |||
| 491 | fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE, | ||
| 492 | fsn_mark); | ||
| 493 | 498 | ||
| 494 | /* Queue ignore event for the watch */ | 499 | /* Queue ignore event for the watch */ |
| 495 | inotify_handle_event(group, FS_IN_IGNORED, NULL, FSNOTIFY_EVENT_NONE, | 500 | inotify_handle_inode_event(fsn_mark, FS_IN_IGNORED, NULL, NULL, NULL, |
| 496 | NULL, NULL, 0, &iter_info); | 501 | 0); |
| 497 | 502 | ||
| 498 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); | 503 | i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark); |
| 499 | /* remove this mark from the idr */ | 504 | /* remove this mark from the idr */ |
| @@ -801,6 +806,18 @@ out: · 301 unmodified lines | |||
| 801 | */ | 806 | */ |
| 802 | static int __init inotify_user_setup(void) | 807 | static int __init inotify_user_setup(void) |
| 803 | { | 808 | { |
| 809 | unsigned long watches_max; | ||
| 810 | struct sysinfo si; | ||
| 811 | |||
| 812 | si_meminfo(&si); | ||
| 813 | /* | ||
| 814 | * Allow up to 1% of addressable memory to be allocated for inotify | ||
| 815 | * watches (per user) limited to the range [8192, 1048576]. | ||
| 816 | */ | ||
| 817 | watches_max = (((si.totalram - si.totalhigh) / 100) << PAGE_SHIFT) / | ||
| 818 | INOTIFY_WATCH_COST; | ||
| 819 | watches_max = clamp(watches_max, 8192UL, 1048576UL); | ||
| 820 | |||
| 804 | BUILD_BUG_ON(IN_ACCESS != FS_ACCESS); | 821 | BUILD_BUG_ON(IN_ACCESS != FS_ACCESS); |
| 805 | BUILD_BUG_ON(IN_MODIFY != FS_MODIFY); | 822 | BUILD_BUG_ON(IN_MODIFY != FS_MODIFY); |
| 806 | BUILD_BUG_ON(IN_ATTRIB != FS_ATTRIB); | 823 | BUILD_BUG_ON(IN_ATTRIB != FS_ATTRIB); |
| @@ -827,7 +844,7 @@ static int __init inotify_user_setup(void) · 20 unmodified lines | |||
| 827 | 844 | ||
| 828 | inotify_max_queued_events = 16384; | 845 | inotify_max_queued_events = 16384; |
| 829 | init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES] = 128; | 846 | init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES] = 128; |
| 830 | init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES] = 8192; | 847 | init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES] = watches_max; |
| 831 | 848 | ||
| 832 | return 0; | 849 | return 0; |
| 833 | } | 850 | } |
| @@ -137,6 +137,7 @@ struct mem_cgroup; · 136 unmodified lines | |||
| 137 | * if @file_name is not NULL, this is the directory that | 137 | * if @file_name is not NULL, this is the directory that |
| 138 | * @file_name is relative to. | 138 | * @file_name is relative to. |
| 139 | * @file_name: optional file name associated with event | 139 | * @file_name: optional file name associated with event |
| 140 | * @cookie: inotify rename cookie | ||
| 140 | * | 141 | * |
| 141 | * free_group_priv - called when a group refcnt hits 0 to clean up the private union | 142 | * free_group_priv - called when a group refcnt hits 0 to clean up the private union |
| 142 | * freeing_mark - called when a mark is being destroyed for some reason. The group | 143 | * freeing_mark - called when a mark is being destroyed for some reason. The group |
| @@ -151,7 +152,7 @@ struct fsnotify_ops { · 8 unmodified lines | |||
| 151 | struct fsnotify_iter_info *iter_info); | 152 | struct fsnotify_iter_info *iter_info); |
| 152 | int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask, | 153 | int (*handle_inode_event)(struct fsnotify_mark *mark, u32 mask, |
| 153 | struct inode *inode, struct inode *dir, | 154 | struct inode *inode, struct inode *dir, |
| 154 | const struct qstr *file_name); | 155 | const struct qstr *file_name, u32 cookie); |
| 155 | void (*free_group_priv)(struct fsnotify_group *group); | 156 | void (*free_group_priv)(struct fsnotify_group *group); |
| 156 | void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); | 157 | void (*freeing_mark)(struct fsnotify_mark *mark, struct fsnotify_group *group); |
| 157 | void (*free_event)(struct fsnotify_event *event); | 158 | void (*free_event)(struct fsnotify_event *event); |
| @@ -277,7 +278,7 @@ static inline const struct path *fsnotify_data_path(const void *data, · 119 unmodified lines | |||
| 277 | 278 | ||
| 278 | enum fsnotify_obj_type { | 279 | enum fsnotify_obj_type { |
| 279 | FSNOTIFY_OBJ_TYPE_INODE, | 280 | FSNOTIFY_OBJ_TYPE_INODE, |
| 280 | FSNOTIFY_OBJ_TYPE_CHILD, | 281 | FSNOTIFY_OBJ_TYPE_PARENT, |
| 281 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, | 282 | FSNOTIFY_OBJ_TYPE_VFSMOUNT, |
| 282 | FSNOTIFY_OBJ_TYPE_SB, | 283 | FSNOTIFY_OBJ_TYPE_SB, |
| 283 | FSNOTIFY_OBJ_TYPE_COUNT, | 284 | FSNOTIFY_OBJ_TYPE_COUNT, |
| @@ -285,7 +286,7 @@ enum fsnotify_obj_type { · 1 unmodified line | |||
| 285 | }; | 286 | }; |
| 286 | 287 | ||
| 287 | #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) | 288 | #define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE) |
| 288 | #define FSNOTIFY_OBJ_TYPE_CHILD_FL (1U << FSNOTIFY_OBJ_TYPE_CHILD) | 289 | #define FSNOTIFY_OBJ_TYPE_PARENT_FL (1U << FSNOTIFY_OBJ_TYPE_PARENT) |
| 289 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) | 290 | #define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT) |
| 290 | #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) | 291 | #define FSNOTIFY_OBJ_TYPE_SB_FL (1U << FSNOTIFY_OBJ_TYPE_SB) |
| 291 | #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) | 292 | #define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1) |
| @@ -330,7 +331,7 @@ static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \ · 38 unmodified lines | |||
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | FSNOTIFY_ITER_FUNCS(inode, INODE) | 333 | FSNOTIFY_ITER_FUNCS(inode, INODE) |
| 333 | FSNOTIFY_ITER_FUNCS(child, CHILD) | 334 | FSNOTIFY_ITER_FUNCS(parent, PARENT) |
| 334 | FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) | 335 | FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT) |
| 335 | FSNOTIFY_ITER_FUNCS(sb, SB) | 336 | FSNOTIFY_ITER_FUNCS(sb, SB) |
| 336 | 337 | ||
| @@ -154,7 +154,7 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark) · 153 unmodified lines | |||
| 154 | /* Update mark data in audit rules based on fsnotify events. */ | 154 | /* Update mark data in audit rules based on fsnotify events. */ |
| 155 | static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, | 155 | static int audit_mark_handle_event(struct fsnotify_mark *inode_mark, u32 mask, |
| 156 | struct inode *inode, struct inode *dir, | 156 | struct inode *inode, struct inode *dir, |
| 157 | const struct qstr *dname) | 157 | const struct qstr *dname, u32 cookie) |
| 158 | { | 158 | { |
| 159 | struct audit_fsnotify_mark *audit_mark; | 159 | struct audit_fsnotify_mark *audit_mark; |
| 160 | 160 | ||
| @@ -1037,7 +1037,7 @@ static void evict_chunk(struct audit_chunk *chunk) · 1036 unmodified lines | |||
| 1037 | 1037 | ||
| 1038 | static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask, | 1038 | static int audit_tree_handle_event(struct fsnotify_mark *mark, u32 mask, |
| 1039 | struct inode *inode, struct inode *dir, | 1039 | struct inode *inode, struct inode *dir, |
| 1040 | const struct qstr *file_name) | 1040 | const struct qstr *file_name, u32 cookie) |
| 1041 | { | 1041 | { |
| 1042 | return 0; | 1042 | return 0; |
| 1043 | } | 1043 | } |
| @@ -466,7 +466,7 @@ void audit_remove_watch_rule(struct audit_krule *krule) · 465 unmodified lines | |||
| 466 | /* Update watch data in audit rules based on fsnotify events. */ | 466 | /* Update watch data in audit rules based on fsnotify events. */ |
| 467 | static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask, | 467 | static int audit_watch_handle_event(struct fsnotify_mark *inode_mark, u32 mask, |
| 468 | struct inode *inode, struct inode *dir, | 468 | struct inode *inode, struct inode *dir, |
| 469 | const struct qstr *dname) | 469 | const struct qstr *dname, u32 cookie) |
| 470 | { | 470 | { |
| 471 | struct audit_parent *parent; | 471 | struct audit_parent *parent; |
| 472 | 472 | ||