/* * If we're not journaling and this is a just-created file, we have to * sync our parent directory (if it was freshly created) since * otherwise it will only be written by writeback, leaving a huge * window during which a crash may lose the file. This may apply for * the parent directory's parent as well, and so on recursively, if * they are also freshly created. */ static int ext4_sync_parent(struct inode *inode) { struct dentry *dentry = NULL; struct inode *next; int ret = 0; if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); dentry = d_find_any_alias(inode); if (!dentry) break; next = igrab(dentry->d_parent->d_inode); dput(dentry); if (!next) break; iput(inode); inode = next; ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; ret = sync_inode_metadata(inode, 1); if (ret) break; } iput(inode); return ret; }
/* drop all shared dentries from other superblocks */ void sdcardfs_drop_sb_icache(struct super_block *sb, unsigned long ino) { struct inode *inode = ilookup(sb, ino); struct dentry *dentry, *dir_dentry; if (!inode) return; dentry = d_find_any_alias(inode); if (!dentry) { iput(inode); return; } dir_dentry = lock_parent(dentry); mutex_lock(&inode->i_mutex); set_nlink(inode, sdcardfs_lower_inode(inode)->i_nlink); d_drop(dentry); dont_mount(dentry); mutex_unlock(&inode->i_mutex); /* We don't d_delete() NFS sillyrenamed files--they still exist. */ if (!(dentry->d_flags & DCACHE_NFSFS_RENAMED)) { fsnotify_link_count(inode); d_delete(dentry); } unlock_dir(dir_dentry); dput(dentry); iput(inode); }
/* * If we're not journaling and this is a just-created file, we have to * sync our parent directory (if it was freshly created) since * otherwise it will only be written by writeback, leaving a huge * window during which a crash may lose the file. This may apply for * the parent directory's parent as well, and so on recursively, if * they are also freshly created. */ static int ext4_sync_parent(struct inode *inode) { struct writeback_control wbc; struct dentry *dentry = NULL; struct inode *next; int ret = 0; if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); dentry = d_find_any_alias(inode); if (!dentry) break; next = igrab(dentry->d_parent->d_inode); dput(dentry); if (!next) break; iput(inode); inode = next; ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; memset(&wbc, 0, sizeof(wbc)); wbc.sync_mode = WB_SYNC_ALL; wbc.nr_to_write = 0; /* only write out the inode */ ret = sync_inode(inode, &wbc); if (ret) break; } iput(inode); return ret; }
static int get_parent_ino(struct inode *inode, nid_t *pino) { struct dentry *dentry; inode = igrab(inode); dentry = d_find_any_alias(inode); iput(inode); if (!dentry) return 0; if (update_dent_inode(inode, inode, &dentry->d_name)) { dput(dentry); return 0; } *pino = parent_ino(dentry); dput(dentry); return 1; }
int ovl_update_time(struct inode *inode, struct timespec *ts, int flags) { struct dentry *alias; struct path upperpath; if (!(flags & S_ATIME)) return 0; alias = d_find_any_alias(inode); if (!alias) return 0; ovl_path_upper(alias, &upperpath); if (upperpath.dentry) { touch_atime(&upperpath); inode->i_atime = d_inode(upperpath.dentry)->i_atime; } dput(alias); return 0; }
void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) { int perm, wkq_err; aufs_bindex_t btop; struct au_dir_ts_arg *arg; struct dentry *dentry; struct super_block *sb; IMustLock(dir); dentry = d_find_any_alias(dir); AuDebugOn(!dentry); sb = dentry->d_sb; btop = au_ibtop(dir); if (btop == bindex) { au_cpup_attr_timesizes(dir); goto out; } perm = au_sbr_perm(sb, btop); if (!au_br_writable(perm)) goto out; arg = kmalloc(sizeof(*arg), GFP_NOFS); if (!arg) goto out; arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */ arg->brid = au_sbr_id(sb, bindex); wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0); if (unlikely(wkq_err)) { pr_err("wkq %d\n", wkq_err); dput(dentry); kfree(arg); } out: dput(dentry); }
/* * If we're not journaling and this is a just-created file, we have to * sync our parent directory (if it was freshly created) since * otherwise it will only be written by writeback, leaving a huge * window during which a crash may lose the file. This may apply for * the parent directory's parent as well, and so on recursively, if * they are also freshly created. */ static int ext4_sync_parent(struct inode *inode) { struct dentry *dentry = NULL; struct inode *next; int ret = 0; if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) return 0; inode = igrab(inode); while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) { ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY); dentry = d_find_any_alias(inode); if (!dentry) break; next = igrab(d_inode(dentry->d_parent)); dput(dentry); if (!next) break; iput(inode); inode = next; /* * The directory inode may have gone through rmdir by now. But * the inode itself and its blocks are still allocated (we hold * a reference to the inode so it didn't go through * ext4_evict_inode()) and so we are safe to flush metadata * blocks and the inode. */ ret = sync_mapping_buffers(inode->i_mapping); if (ret) break; ret = sync_inode_metadata(inode, 1); if (ret) break; } iput(inode); return ret; }
int ovl_permission(struct inode *inode, int mask) { struct ovl_entry *oe; struct dentry *alias = NULL; struct inode *realinode; struct dentry *realdentry; bool is_upper; int err; if (S_ISDIR(inode->i_mode)) { oe = inode->i_private; } else if (mask & MAY_NOT_BLOCK) { return -ECHILD; } else { /* * For non-directories find an alias and get the info * from there. */ alias = d_find_any_alias(inode); if (WARN_ON(!alias)) return -ENOENT; oe = alias->d_fsdata; } realdentry = ovl_entry_real(oe, &is_upper); /* Careful in RCU walk mode */ realinode = ACCESS_ONCE(realdentry->d_inode); if (!realinode) { WARN_ON(!(mask & MAY_NOT_BLOCK)); err = -ENOENT; goto out_dput; } if (mask & MAY_WRITE) { umode_t mode = realinode->i_mode; /* * Writes will always be redirected to upper layer, so * ignore lower layer being read-only. * * If the overlay itself is read-only then proceed * with the permission check, don't return EROFS. * This will only happen if this is the lower layer of * another overlayfs. * * If upper fs becomes read-only after the overlay was * constructed return EROFS to prevent modification of * upper layer. */ err = -EROFS; if (is_upper && !IS_RDONLY(inode) && IS_RDONLY(realinode) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) goto out_dput; } err = __inode_permission(realinode, mask); out_dput: dput(alias); return err; }